* [PATCH v2 0/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360
@ 2020-06-19 11:53 Gene Chen
2020-06-19 11:53 ` [PATCH v2 1/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 PMIC Gene Chen
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Gene Chen @ 2020-06-19 11:53 UTC (permalink / raw)
To: lee.jones, jic23, jacek.anaszewski, pavel, matthias.bgg
Cc: gene_chen, lars, lgirdwood, linux-kernel, cy_huang,
benjamin.chao, broonie, linux-mediatek, dmurphy, pmeerw,
knaack.h, linux-arm-kernel, shufan_lee
This patch series add mt6360 sub-device adc/regulator and
fix mfd architecture and add dt-binding document
changelogs between v1 & v2
- adjust binding document schema include mfd/adc/regulator
- adc: use IIO_CHAN_INFO_PROCESSED only
- adc: use devm_iio_triggered_buffer_setup
- adc: use use s64 to record timestamp
- regulator: merge regmap to mfd driver for r/w with crc
Gene Chen (4)
dt-bindings: mfd: Add bindings for the Mediatek MT6360
mfd: mt6360: implement i2c R/W with CRC
iio: adc: mt6360: Add ADC driver for MT6360
regulator: mt6360: Add support for MT6360 regulator
Documentation/devicetree/bindings/mfd/mt6360.txt | 122 +++++
drivers/iio/adc/Kconfig | 11
drivers/iio/adc/Makefile | 1
drivers/iio/adc/mt6360-adc.c | 388 ++++++++++++++++
drivers/mfd/Kconfig | 1
drivers/mfd/mt6360-core.c | 541 +++++++++++++++--------
drivers/regulator/Kconfig | 9
drivers/regulator/Makefile | 1
drivers/regulator/mt6360-regulator.c | 485 ++++++++++++++++++++
include/dt-bindings/mfd/mt6360.h | 15
include/linux/mfd/mt6360.h | 240 ----------
11 files changed, 1389 insertions(+), 425 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mfd/mt6360.txt
create mode 100644 include/dt-bindings/mfd/mt6360.h
delete mode 100644 include/linux/mfd/mt6360.h
create mode 100644 drivers/iio/adc/mt6360-adc.c
create mode 100644 drivers/regulator/mt6360-regulator.c
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 1/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 PMIC
2020-06-19 11:53 [PATCH v2 0/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 Gene Chen
@ 2020-06-19 11:53 ` Gene Chen
2020-06-19 11:53 ` [PATCH v2 2/4] mfd: mt6360: implement i2c R/W with CRC Gene Chen
` (3 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Gene Chen @ 2020-06-19 11:53 UTC (permalink / raw)
To: lee.jones, jic23, jacek.anaszewski, pavel, matthias.bgg
Cc: gene_chen, lars, lgirdwood, linux-kernel, cy_huang,
benjamin.chao, broonie, linux-mediatek, dmurphy, pmeerw,
knaack.h, linux-arm-kernel, shufan_lee
From: Gene Chen <gene_chen@richtek.com>
Add devicetree binding document support Mediatek MT6360 PMIC
Signed-off-by: Gene Chen <gene_chen@richtek.com>
---
Documentation/devicetree/bindings/mfd/mt6360.txt | 122 +++++++++++++++++++++++
include/dt-bindings/mfd/mt6360.h | 15 +++
2 files changed, 137 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/mt6360.txt
create mode 100644 include/dt-bindings/mfd/mt6360.h
diff --git a/Documentation/devicetree/bindings/mfd/mt6360.txt b/Documentation/devicetree/bindings/mfd/mt6360.txt
new file mode 100644
index 0000000..7d7d349
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mt6360.txt
@@ -0,0 +1,122 @@
+MediaTek MT6360 PMIC Driver
+
+MT6360 is a multifunction device with the following sub modules:
+It is interfaced to host controller using I2C interface.
+This document describes the binding for PMIC device and its sub module.
+
+- ADC
+- Battery Charger/OTG boost
+- Flash LED/RGB LED/moonlight LED
+- 2-channel Buck and 6-channel LDO
+- USB_PD
+
+Required properties:
+- compatible: Must be "mediatek,mt6360-pmu"
+- reg: Specifies the I2C slave address of PMIC block, Must be <0x34>
+- interrupts: I2C device IRQ line connected to the main SoC.
+
+Optional subnodes:
+- ADC
+ Required properties:
+ - compatible: "mediatek,mt6360-adc"
+- battery charger/OTG boost
+ Required properties:
+ - compatible: "mediatek,mt6360-chg"
+- Flash LED/RGB LED/moonlight LED
+ Required properties:
+ - compatible: "mediatek,mt6360-led"
+- 2-channel Buck and 6-channel LDO
+ Required properties:
+ - compatible: "mediatek,mt6360-regulator"
+- USB_PD
+ Required properties:
+ - compatible: "mediatek,mt6360-tcpc"
+
+Example:
+
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/mfd/mt6360.h>
+
+ mt6360@34 {
+ compatible = "mediatek,mt6360";
+ reg = <0x34>;
+ wakeup-source;
+ interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "IRQB";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ adc {
+ compatible = "mediatek,mt6360-adc";
+ #io-channel-cells = <1>;
+ };
+ regulator {
+ compatible = "mediatek,mt6360-regulator";
+ LDO_VIN3-supply = <&BUCK2>;
+ buck1 {
+ regulator-compatible = "BUCK1";
+ regulator-name = "mt6360,buck1";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP
+ MT6360_OPMODE_ULP>;
+ };
+ BUCK2: buck2 {
+ regulator-compatible = "BUCK2";
+ regulator-name = "mt6360,buck2";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP
+ MT6360_OPMODE_ULP>;
+ };
+ ldo6 {
+ regulator-compatible = "LDO6";
+ regulator-name = "mt6360,ldo6";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <2100000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+ ldo7 {
+ regulator-compatible = "LDO7";
+ regulator-name = "mt6360,ldo7";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <2100000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+ ldo1 {
+ regulator-compatible = "LDO1";
+ regulator-name = "mt6360,ldo1";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3600000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+ ldo2 {
+ regulator-compatible = "LDO2";
+ regulator-name = "mt6360,ldo2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3600000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+ ldo3 {
+ regulator-compatible = "LDO3";
+ regulator-name = "mt6360,ldo3";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3600000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+ ldo5 {
+ regulator-compatible = "LDO5";
+ regulator-name = "mt6360,ldo5";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3600000>;
+ regulator-allowed-modes = <MT6360_OPMODE_NORMAL
+ MT6360_OPMODE_LP>;
+ };
+ };
+ };
diff --git a/include/dt-bindings/mfd/mt6360.h b/include/dt-bindings/mfd/mt6360.h
new file mode 100644
index 0000000..6368388
--- /dev/null
+++ b/include/dt-bindings/mfd/mt6360.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides macros for MT6360 device bindings.
+ *
+ * Copyright (c) 2020 Mediatek Inc.
+ */
+
+#ifndef __DT_BINDINGS_MT6360_H__
+#define __DT_BINDINGS_MT6360_H__
+
+#define MT6360_OPMODE_LP (2)
+#define MT6360_OPMODE_ULP (3)
+#define MT6360_OPMODE_NORMAL (0)
+
+#endif /* __DT_BINDINGS_MT6360_H__ */
--
2.7.4
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 2/4] mfd: mt6360: implement i2c R/W with CRC
2020-06-19 11:53 [PATCH v2 0/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 Gene Chen
2020-06-19 11:53 ` [PATCH v2 1/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 PMIC Gene Chen
@ 2020-06-19 11:53 ` Gene Chen
2020-07-01 7:16 ` Lee Jones
2020-06-19 11:53 ` [PATCH v2 3/4] iio: adc: mt6360: Add ADC driver for MT6360 Gene Chen
` (2 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Gene Chen @ 2020-06-19 11:53 UTC (permalink / raw)
To: lee.jones, jic23, jacek.anaszewski, pavel, matthias.bgg
Cc: gene_chen, lars, lgirdwood, linux-kernel, cy_huang,
benjamin.chao, broonie, linux-mediatek, dmurphy, pmeerw,
knaack.h, linux-arm-kernel, shufan_lee
From: Gene Chen <gene_chen@richtek.com>
imlement i2c R/W with CRC when access sub-device PMIC and LDO part
Signed-off-by: Gene Chen <gene_chen@richtek.com>
---
drivers/mfd/Kconfig | 1 +
drivers/mfd/mt6360-core.c | 541 +++++++++++++++++++++++++++++----------------
include/linux/mfd/mt6360.h | 240 --------------------
3 files changed, 357 insertions(+), 425 deletions(-)
delete mode 100644 include/linux/mfd/mt6360.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index a37d7d1..0684ddc 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -913,6 +913,7 @@ config MFD_MT6360
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
+ select CRC8
depends on I2C
help
Say Y here to enable MT6360 PMU/PMIC/LDO functional support.
diff --git a/drivers/mfd/mt6360-core.c b/drivers/mfd/mt6360-core.c
index e9cacc2..00e3cb5 100644
--- a/drivers/mfd/mt6360-core.c
+++ b/drivers/mfd/mt6360-core.c
@@ -5,122 +5,160 @@
* Author: Gene Chen <gene_chen@richtek.com>
*/
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/i2c.h>
-#include <linux/init.h>
+#include <linux/crc8.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
#include <linux/interrupt.h>
-#include <linux/kernel.h>
#include <linux/mfd/core.h>
-#include <linux/module.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/version.h>
-#include <linux/mfd/mt6360.h>
+enum {
+ MT6360_SLAVE_TCPC = 0,
+ MT6360_SLAVE_PMIC,
+ MT6360_SLAVE_LDO,
+ MT6360_SLAVE_PMU,
+ MT6360_SLAVE_MAX,
+};
+
+struct mt6360_data {
+ struct i2c_client *i2c[MT6360_SLAVE_MAX];
+ struct device *dev;
+ struct regmap *regmap;
+ struct regmap_irq_chip_data *irq_data;
+ unsigned int chip_rev;
+ u8 crc8_tbl[CRC8_TABLE_SIZE];
+};
+
+#define MT6360_PMU_SLAVEID 0x34
+#define MT6360_PMIC_SLAVEID 0x1A
+#define MT6360_LDO_SLAVEID 0x64
+#define MT6360_TCPC_SLAVEID 0x4E
+
+#define MT6360_REG_TCPCSTART 0x00
+#define MT6360_REG_TCPCEND 0xFF
+#define MT6360_REG_PMICSTART 0x100
+#define MT6360_REG_PMICEND 0x13B
+#define MT6360_REG_LDOSTART 0x200
+#define MT6360_REG_LDOEND 0x21C
+#define MT6360_REG_PMUSTART 0x300
+#define MT6360_REG_PMU_DEVINFO 0x300
+#define MT6360_REG_PMU_CHGIRQ1 0x3D0
+#define MT6360_REG_PMU_CHGMASK1 0x3F0
+#define MT6360_REG_PMUEND 0x3FF
+
+/* from 0x3D0 to 0x3DF */
+#define MT6360_IRQ_REGNUM 16
+
+#define MT6360_CHIPVEN_MASK 0xF0
+#define MT6360_CHIPVEN_VAL 0x50
+#define MT6360_CHIPREV_MASK 0x0F
/* reg 0 -> 0 ~ 7 */
-#define MT6360_CHG_TREG_EVT (4)
-#define MT6360_CHG_AICR_EVT (5)
-#define MT6360_CHG_MIVR_EVT (6)
-#define MT6360_PWR_RDY_EVT (7)
+#define MT6360_CHG_TREG_EVT 4
+#define MT6360_CHG_AICR_EVT 5
+#define MT6360_CHG_MIVR_EVT 6
+#define MT6360_PWR_RDY_EVT 7
/* REG 1 -> 8 ~ 15 */
-#define MT6360_CHG_BATSYSUV_EVT (9)
-#define MT6360_FLED_CHG_VINOVP_EVT (11)
-#define MT6360_CHG_VSYSUV_EVT (12)
-#define MT6360_CHG_VSYSOV_EVT (13)
-#define MT6360_CHG_VBATOV_EVT (14)
-#define MT6360_CHG_VBUSOV_EVT (15)
+#define MT6360_CHG_BATSYSUV_EVT 9
+#define MT6360_FLED_CHG_VINOVP_EVT 11
+#define MT6360_CHG_VSYSUV_EVT 12
+#define MT6360_CHG_VSYSOV_EVT 13
+#define MT6360_CHG_VBATOV_EVT 14
+#define MT6360_CHG_VBUSOV_EVT 15
/* REG 2 -> 16 ~ 23 */
/* REG 3 -> 24 ~ 31 */
-#define MT6360_WD_PMU_DET (25)
-#define MT6360_WD_PMU_DONE (26)
-#define MT6360_CHG_TMRI (27)
-#define MT6360_CHG_ADPBADI (29)
-#define MT6360_CHG_RVPI (30)
-#define MT6360_OTPI (31)
+#define MT6360_WD_PMU_DET 25
+#define MT6360_WD_PMU_DONE 26
+#define MT6360_CHG_TMRI 27
+#define MT6360_CHG_ADPBADI 29
+#define MT6360_CHG_RVPI 30
+#define MT6360_OTPI 31
/* REG 4 -> 32 ~ 39 */
-#define MT6360_CHG_AICCMEASL (32)
-#define MT6360_CHGDET_DONEI (34)
-#define MT6360_WDTMRI (35)
-#define MT6360_SSFINISHI (36)
-#define MT6360_CHG_RECHGI (37)
-#define MT6360_CHG_TERMI (38)
-#define MT6360_CHG_IEOCI (39)
+#define MT6360_CHG_AICCMEASL 32
+#define MT6360_CHGDET_DONEI 34
+#define MT6360_WDTMRI 35
+#define MT6360_SSFINISHI 36
+#define MT6360_CHG_RECHGI 37
+#define MT6360_CHG_TERMI 38
+#define MT6360_CHG_IEOCI 39
/* REG 5 -> 40 ~ 47 */
-#define MT6360_PUMPX_DONEI (40)
-#define MT6360_BAT_OVP_ADC_EVT (41)
-#define MT6360_TYPEC_OTP_EVT (42)
-#define MT6360_ADC_WAKEUP_EVT (43)
-#define MT6360_ADC_DONEI (44)
-#define MT6360_BST_BATUVI (45)
-#define MT6360_BST_VBUSOVI (46)
-#define MT6360_BST_OLPI (47)
+#define MT6360_PUMPX_DONEI 40
+#define MT6360_BAT_OVP_ADC_EVT 41
+#define MT6360_TYPEC_OTP_EVT 42
+#define MT6360_ADC_WAKEUP_EVT 43
+#define MT6360_ADC_DONEI 44
+#define MT6360_BST_BATUVI 45
+#define MT6360_BST_VBUSOVI 46
+#define MT6360_BST_OLPI 47
/* REG 6 -> 48 ~ 55 */
-#define MT6360_ATTACH_I (48)
-#define MT6360_DETACH_I (49)
-#define MT6360_QC30_STPDONE (51)
-#define MT6360_QC_VBUSDET_DONE (52)
-#define MT6360_HVDCP_DET (53)
-#define MT6360_CHGDETI (54)
-#define MT6360_DCDTI (55)
+#define MT6360_ATTACH_I 48
+#define MT6360_DETACH_I 49
+#define MT6360_QC30_STPDONE 51
+#define MT6360_QC_VBUSDET_DONE 52
+#define MT6360_HVDCP_DET 53
+#define MT6360_CHGDETI 54
+#define MT6360_DCDTI 55
/* REG 7 -> 56 ~ 63 */
-#define MT6360_FOD_DONE_EVT (56)
-#define MT6360_FOD_OV_EVT (57)
-#define MT6360_CHRDET_UVP_EVT (58)
-#define MT6360_CHRDET_OVP_EVT (59)
-#define MT6360_CHRDET_EXT_EVT (60)
-#define MT6360_FOD_LR_EVT (61)
-#define MT6360_FOD_HR_EVT (62)
-#define MT6360_FOD_DISCHG_FAIL_EVT (63)
+#define MT6360_FOD_DONE_EVT 56
+#define MT6360_FOD_OV_EVT 57
+#define MT6360_CHRDET_UVP_EVT 58
+#define MT6360_CHRDET_OVP_EVT 59
+#define MT6360_CHRDET_EXT_EVT 60
+#define MT6360_FOD_LR_EVT 61
+#define MT6360_FOD_HR_EVT 62
+#define MT6360_FOD_DISCHG_FAIL_EVT 63
/* REG 8 -> 64 ~ 71 */
-#define MT6360_USBID_EVT (64)
-#define MT6360_APWDTRST_EVT (65)
-#define MT6360_EN_EVT (66)
-#define MT6360_QONB_RST_EVT (67)
-#define MT6360_MRSTB_EVT (68)
-#define MT6360_OTP_EVT (69)
-#define MT6360_VDDAOV_EVT (70)
-#define MT6360_SYSUV_EVT (71)
+#define MT6360_USBID_EVT 64
+#define MT6360_APWDTRST_EVT 65
+#define MT6360_EN_EVT 66
+#define MT6360_QONB_RST_EVT 67
+#define MT6360_MRSTB_EVT 68
+#define MT6360_OTP_EVT 69
+#define MT6360_VDDAOV_EVT 70
+#define MT6360_SYSUV_EVT 71
/* REG 9 -> 72 ~ 79 */
-#define MT6360_FLED_STRBPIN_EVT (72)
-#define MT6360_FLED_TORPIN_EVT (73)
-#define MT6360_FLED_TX_EVT (74)
-#define MT6360_FLED_LVF_EVT (75)
-#define MT6360_FLED2_SHORT_EVT (78)
-#define MT6360_FLED1_SHORT_EVT (79)
+#define MT6360_FLED_STRBPIN_EVT 72
+#define MT6360_FLED_TORPIN_EVT 73
+#define MT6360_FLED_TX_EVT 74
+#define MT6360_FLED_LVF_EVT 75
+#define MT6360_FLED2_SHORT_EVT 78
+#define MT6360_FLED1_SHORT_EVT 79
/* REG 10 -> 80 ~ 87 */
-#define MT6360_FLED2_STRB_EVT (80)
-#define MT6360_FLED1_STRB_EVT (81)
-#define MT6360_FLED2_STRB_TO_EVT (82)
-#define MT6360_FLED1_STRB_TO_EVT (83)
-#define MT6360_FLED2_TOR_EVT (84)
-#define MT6360_FLED1_TOR_EVT (85)
+#define MT6360_FLED2_STRB_EVT 80
+#define MT6360_FLED1_STRB_EVT 81
+#define MT6360_FLED2_STRB_TO_EVT 82
+#define MT6360_FLED1_STRB_TO_EVT 83
+#define MT6360_FLED2_TOR_EVT 84
+#define MT6360_FLED1_TOR_EVT 85
/* REG 11 -> 88 ~ 95 */
/* REG 12 -> 96 ~ 103 */
-#define MT6360_BUCK1_PGB_EVT (96)
-#define MT6360_BUCK1_OC_EVT (100)
-#define MT6360_BUCK1_OV_EVT (101)
-#define MT6360_BUCK1_UV_EVT (102)
+#define MT6360_BUCK1_PGB_EVT 96
+#define MT6360_BUCK1_OC_EVT 100
+#define MT6360_BUCK1_OV_EVT 101
+#define MT6360_BUCK1_UV_EVT 102
/* REG 13 -> 104 ~ 111 */
-#define MT6360_BUCK2_PGB_EVT (104)
-#define MT6360_BUCK2_OC_EVT (108)
-#define MT6360_BUCK2_OV_EVT (109)
-#define MT6360_BUCK2_UV_EVT (110)
+#define MT6360_BUCK2_PGB_EVT 104
+#define MT6360_BUCK2_OC_EVT 108
+#define MT6360_BUCK2_OV_EVT 109
+#define MT6360_BUCK2_UV_EVT 110
/* REG 14 -> 112 ~ 119 */
-#define MT6360_LDO1_OC_EVT (113)
-#define MT6360_LDO2_OC_EVT (114)
-#define MT6360_LDO3_OC_EVT (115)
-#define MT6360_LDO5_OC_EVT (117)
-#define MT6360_LDO6_OC_EVT (118)
-#define MT6360_LDO7_OC_EVT (119)
+#define MT6360_LDO1_OC_EVT 113
+#define MT6360_LDO2_OC_EVT 114
+#define MT6360_LDO3_OC_EVT 115
+#define MT6360_LDO5_OC_EVT 117
+#define MT6360_LDO6_OC_EVT 118
+#define MT6360_LDO7_OC_EVT 119
/* REG 15 -> 120 ~ 127 */
-#define MT6360_LDO1_PGB_EVT (121)
-#define MT6360_LDO2_PGB_EVT (122)
-#define MT6360_LDO3_PGB_EVT (123)
-#define MT6360_LDO5_PGB_EVT (125)
-#define MT6360_LDO6_PGB_EVT (126)
-#define MT6360_LDO7_PGB_EVT (127)
-
-static const struct regmap_irq mt6360_pmu_irqs[] = {
+#define MT6360_LDO1_PGB_EVT 121
+#define MT6360_LDO2_PGB_EVT 122
+#define MT6360_LDO3_PGB_EVT 123
+#define MT6360_LDO5_PGB_EVT 125
+#define MT6360_LDO6_PGB_EVT 126
+#define MT6360_LDO7_PGB_EVT 127
+
+static const struct regmap_irq mt6360_irqs[] = {
REGMAP_IRQ_REG_LINE(MT6360_CHG_TREG_EVT, 8),
REGMAP_IRQ_REG_LINE(MT6360_CHG_AICR_EVT, 8),
REGMAP_IRQ_REG_LINE(MT6360_CHG_MIVR_EVT, 8),
@@ -209,30 +247,16 @@ static const struct regmap_irq mt6360_pmu_irqs[] = {
REGMAP_IRQ_REG_LINE(MT6360_LDO7_PGB_EVT, 8),
};
-static int mt6360_pmu_handle_post_irq(void *irq_drv_data)
-{
- struct mt6360_pmu_data *mpd = irq_drv_data;
-
- return regmap_update_bits(mpd->regmap,
- MT6360_PMU_IRQ_SET, MT6360_IRQ_RETRIG, MT6360_IRQ_RETRIG);
-}
-
-static struct regmap_irq_chip mt6360_pmu_irq_chip = {
- .irqs = mt6360_pmu_irqs,
- .num_irqs = ARRAY_SIZE(mt6360_pmu_irqs),
- .num_regs = MT6360_PMU_IRQ_REGNUM,
- .mask_base = MT6360_PMU_CHG_MASK1,
- .status_base = MT6360_PMU_CHG_IRQ1,
- .ack_base = MT6360_PMU_CHG_IRQ1,
+static const struct regmap_irq_chip mt6360_irq_chip = {
+ .name = "mt6360_irqs",
+ .irqs = mt6360_irqs,
+ .num_irqs = ARRAY_SIZE(mt6360_irqs),
+ .num_regs = MT6360_IRQ_REGNUM,
+ .mask_base = MT6360_REG_PMU_CHGMASK1,
+ .status_base = MT6360_REG_PMU_CHGIRQ1,
+ .ack_base = MT6360_REG_PMU_CHGIRQ1,
.init_ack_masked = true,
.use_ack = true,
- .handle_post_irq = mt6360_pmu_handle_post_irq,
-};
-
-static const struct regmap_config mt6360_pmu_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = MT6360_PMU_MAXREG,
};
static const struct resource mt6360_adc_resources[] = {
@@ -266,7 +290,7 @@ static const struct resource mt6360_led_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6360_FLED1_STRB_TO_EVT, "fled1_strb_to_evt"),
};
-static const struct resource mt6360_pmic_resources[] = {
+static const struct resource mt6360_regulator_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_PGB_EVT, "buck1_pgb_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_OC_EVT, "buck1_oc_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_OV_EVT, "buck1_ov_evt"),
@@ -279,9 +303,6 @@ static const struct resource mt6360_pmic_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6360_LDO7_OC_EVT, "ldo7_oc_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_LDO6_PGB_EVT, "ldo6_pgb_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_LDO7_PGB_EVT, "ldo7_pgb_evt"),
-};
-
-static const struct resource mt6360_ldo_resources[] = {
DEFINE_RES_IRQ_NAMED(MT6360_LDO1_OC_EVT, "ldo1_oc_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_LDO2_OC_EVT, "ldo2_oc_evt"),
DEFINE_RES_IRQ_NAMED(MT6360_LDO3_OC_EVT, "ldo3_oc_evt"),
@@ -293,94 +314,245 @@ static const struct resource mt6360_ldo_resources[] = {
};
static const struct mfd_cell mt6360_devs[] = {
- OF_MFD_CELL("mt6360_adc", mt6360_adc_resources,
- NULL, 0, 0, "mediatek,mt6360_adc"),
- OF_MFD_CELL("mt6360_chg", mt6360_chg_resources,
- NULL, 0, 0, "mediatek,mt6360_chg"),
- OF_MFD_CELL("mt6360_led", mt6360_led_resources,
- NULL, 0, 0, "mediatek,mt6360_led"),
- OF_MFD_CELL("mt6360_pmic", mt6360_pmic_resources,
- NULL, 0, 0, "mediatek,mt6360_pmic"),
- OF_MFD_CELL("mt6360_ldo", mt6360_ldo_resources,
- NULL, 0, 0, "mediatek,mt6360_ldo"),
- OF_MFD_CELL("mt6360_tcpc", NULL,
- NULL, 0, 0, "mediatek,mt6360_tcpc"),
+ OF_MFD_CELL("mt6360-adc", mt6360_adc_resources,
+ NULL, 0, 0, "mediatek,mt6360-adc"),
+ OF_MFD_CELL("mt6360-chg", mt6360_chg_resources,
+ NULL, 0, 0, "mediatek,mt6360-chg"),
+ OF_MFD_CELL("mt6360-led", mt6360_led_resources,
+ NULL, 0, 0, "mediatek,mt6360-led"),
+ OF_MFD_CELL("mt6360-regulator", mt6360_regulator_resources,
+ NULL, 0, 0, "mediatek,mt6360-regulator"),
+ OF_MFD_CELL("mt6360-tcpc", NULL,
+ NULL, 0, 0, "mediatek,mt6360-tcpc"),
};
-static const unsigned short mt6360_slave_addr[MT6360_SLAVE_MAX] = {
- MT6360_PMU_SLAVEID,
+static int mt6360_check_vendor_info(struct mt6360_data *data)
+{
+ u32 info;
+ int ret;
+
+ ret = regmap_read(data->regmap, MT6360_REG_PMU_DEVINFO, &info);
+ if (ret < 0)
+ return ret;
+
+ if ((info & MT6360_CHIPVEN_MASK) != MT6360_CHIPVEN_VAL)
+ return -ENODEV;
+
+ data->chip_rev = info & MT6360_CHIPREV_MASK;
+
+ return 0;
+}
+
+static const u16 mt6360_slave_addrs[MT6360_SLAVE_MAX] = {
+ MT6360_TCPC_SLAVEID,
MT6360_PMIC_SLAVEID,
MT6360_LDO_SLAVEID,
- MT6360_TCPC_SLAVEID,
+ MT6360_PMU_SLAVEID,
};
-static int mt6360_pmu_probe(struct i2c_client *client)
+static int mt6360_xlate_pmicldo_addr(u8 *addr, int rw_size)
{
- struct mt6360_pmu_data *mpd;
- unsigned int reg_data;
- int i, ret;
+ u8 flags[4] = { 0x00, 0x40, 0x80, 0xc0 };
+
+ if (rw_size < 1 || rw_size > 4)
+ return -EINVAL;
- mpd = devm_kzalloc(&client->dev, sizeof(*mpd), GFP_KERNEL);
- if (!mpd)
+ *addr &= 0x3f;
+ *addr |= flags[rw_size - 1];
+
+ return 0;
+}
+
+static int mt6360_regmap_read(void *context, const void *reg, size_t reg_size,
+ void *val, size_t val_size)
+{
+ struct mt6360_data *data = context;
+ u8 bank = *(u8 *)reg, reg_addr = *(u8 *)(reg + 1);
+ struct i2c_client *i2c = data->i2c[bank];
+ bool crc_needed = false;
+ u8 *buf;
+ /* first two is i2c_addr + reg_addr , last is crc8 */
+ int alloc_size = 2 + val_size + 1, read_size = val_size;
+ u8 crc;
+ int ret;
+
+ if (bank == MT6360_SLAVE_PMIC || bank == MT6360_SLAVE_LDO) {
+ crc_needed = true;
+ ret = mt6360_xlate_pmicldo_addr(®_addr, val_size);
+ if (ret < 0)
+ return ret;
+ read_size += 1;
+ }
+
+ buf = kzalloc(alloc_size, GFP_KERNEL);
+ if (!buf)
return -ENOMEM;
- mpd->dev = &client->dev;
- i2c_set_clientdata(client, mpd);
+ /* 7 bit slave addr + read bit */
+ buf[0] = ((i2c->addr & 0x7f) << 1) + 1;
+ buf[1] = reg_addr;
- mpd->regmap = devm_regmap_init_i2c(client, &mt6360_pmu_regmap_config);
- if (IS_ERR(mpd->regmap)) {
- dev_err(&client->dev, "Failed to register regmap\n");
- return PTR_ERR(mpd->regmap);
+ ret = i2c_smbus_read_i2c_block_data(i2c, reg_addr, read_size, buf + 2);
+
+ if (ret == read_size) {
+ memcpy(val, buf + 2, val_size);
+ if (crc_needed) {
+ crc = crc8(data->crc8_tbl, buf, val_size + 2, 0);
+ if (crc != buf[val_size + 2])
+ ret = -EIO;
+ }
}
- ret = regmap_read(mpd->regmap, MT6360_PMU_DEV_INFO, ®_data);
- if (ret) {
- dev_err(&client->dev, "Device not found\n");
+ kfree(buf);
+
+ if (ret < 0)
return ret;
+ else if (ret != read_size)
+ return -EIO;
+
+ return 0;
+}
+
+static int mt6360_regmap_write(void *context, const void *val, size_t val_size)
+{
+ struct mt6360_data *data = context;
+ u8 bank = *(u8 *)val, reg_addr = *(u8 *)(val + 1);
+ struct i2c_client *i2c = data->i2c[bank];
+ bool crc_needed = false;
+ u8 *buf;
+ /* first two is i2c_addr + reg_addr , last crc8 + dummy */
+ int alloc_size = 2 + val_size + 2, write_size = val_size - 2;
+ int ret;
+
+ if (bank == MT6360_SLAVE_PMIC || bank == MT6360_SLAVE_LDO) {
+ crc_needed = true;
+ ret = mt6360_xlate_pmicldo_addr(®_addr, val_size - 2);
+ if (ret < 0)
+ return ret;
}
- mpd->chip_rev = reg_data & CHIP_REV_MASK;
- if (mpd->chip_rev != CHIP_VEN_MT6360) {
- dev_err(&client->dev, "Device not supported\n");
- return -ENODEV;
+ buf = kzalloc(alloc_size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* 7 bit slave addr + write bit */
+ buf[0] = ((i2c->addr & 0x7f) << 1);
+ buf[1] = reg_addr;
+ /* val need to minus regaddr 16bit */
+ memcpy(buf + 2, val + 2, write_size);
+
+ if (crc_needed) {
+ buf[val_size] = crc8(data->crc8_tbl, buf, val_size, 0);
+ write_size += 2;
}
- mt6360_pmu_irq_chip.irq_drv_data = mpd;
- ret = devm_regmap_add_irq_chip(&client->dev, mpd->regmap, client->irq,
- IRQF_TRIGGER_FALLING, 0,
- &mt6360_pmu_irq_chip, &mpd->irq_data);
- if (ret) {
- dev_err(&client->dev, "Failed to add Regmap IRQ Chip\n");
+ ret = i2c_smbus_write_i2c_block_data(i2c,
+ reg_addr, write_size, buf + 2);
+
+ kfree(buf);
+
+ if (ret < 0)
return ret;
+
+ return 0;
+}
+
+static const struct regmap_bus mt6360_regmap_bus = {
+ .read = mt6360_regmap_read,
+ .write = mt6360_regmap_write,
+
+ /* due to pmic and ldo crc access size limit */
+ .max_raw_read = 4,
+ .max_raw_write = 4,
+};
+
+static bool mt6360_is_readwrite_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MT6360_REG_TCPCSTART ... MT6360_REG_TCPCEND:
+ case MT6360_REG_PMICSTART ... MT6360_REG_PMICEND:
+ case MT6360_REG_LDOSTART ... MT6360_REG_LDOEND:
+ fallthrough;
+ case MT6360_REG_PMUSTART ... MT6360_REG_PMUEND:
+ return true;
}
- mpd->i2c[0] = client;
- for (i = 1; i < MT6360_SLAVE_MAX; i++) {
- mpd->i2c[i] = devm_i2c_new_dummy_device(&client->dev,
- client->adapter,
- mt6360_slave_addr[i]);
- if (IS_ERR(mpd->i2c[i])) {
+ return false;
+}
+
+static const struct regmap_config mt6360_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+
+ /* bank1:tcpc, bank2:pmic, bank3:ldo, bank4:pmu */
+ .max_register = MT6360_REG_PMUEND,
+ .writeable_reg = mt6360_is_readwrite_reg,
+ .readable_reg = mt6360_is_readwrite_reg,
+};
+
+static int mt6360_probe(struct i2c_client *client)
+{
+ struct mt6360_data *data;
+ int i, ret;
+
+ data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->dev = &client->dev;
+ crc8_populate_msb(data->crc8_tbl, 0x7);
+
+ for (i = 0; i < MT6360_SLAVE_PMU; i++) {
+ data->i2c[i] = devm_i2c_new_dummy_device(&client->dev,
+ client->adapter,
+ mt6360_slave_addrs[i]);
+ if (IS_ERR(data->i2c[i])) {
dev_err(&client->dev,
"Failed to get new dummy I2C device for address 0x%x",
- mt6360_slave_addr[i]);
- return PTR_ERR(mpd->i2c[i]);
+ mt6360_slave_addrs[i]);
+ return PTR_ERR(data->i2c[i]);
}
- i2c_set_clientdata(mpd->i2c[i], mpd);
+ }
+ data->i2c[MT6360_SLAVE_PMU] = client;
+
+ data->regmap = devm_regmap_init(&client->dev, &mt6360_regmap_bus,
+ data, &mt6360_regmap_config);
+ if (IS_ERR(data->regmap)) {
+ dev_err(&client->dev, "Failed to register regmap\n");
+ return PTR_ERR(data->regmap);
+ }
+
+ ret = mt6360_check_vendor_info(data);
+ if (ret) {
+ dev_err(&client->dev, "Device not supported\n");
+ return ret;
+ }
+
+ ret = devm_regmap_add_irq_chip(&client->dev, data->regmap, client->irq,
+ IRQF_ONESHOT, 0, &mt6360_irq_chip,
+ &data->irq_data);
+ if (ret) {
+ dev_err(&client->dev, "Failed to add Regmap IRQ Chip\n");
+ return ret;
}
ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO,
mt6360_devs, ARRAY_SIZE(mt6360_devs), NULL,
- 0, regmap_irq_get_domain(mpd->irq_data));
+ 0, regmap_irq_get_domain(data->irq_data));
if (ret) {
dev_err(&client->dev,
"Failed to register subordinate devices\n");
return ret;
}
+ i2c_set_clientdata(client, data);
+
return 0;
}
-static int __maybe_unused mt6360_pmu_suspend(struct device *dev)
+static int __maybe_unused mt6360_suspend(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
@@ -390,7 +562,7 @@ static int __maybe_unused mt6360_pmu_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused mt6360_pmu_resume(struct device *dev)
+static int __maybe_unused mt6360_resume(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
@@ -401,25 +573,24 @@ static int __maybe_unused mt6360_pmu_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(mt6360_pmu_pm_ops,
- mt6360_pmu_suspend, mt6360_pmu_resume);
+static SIMPLE_DEV_PM_OPS(mt6360_pm_ops, mt6360_suspend, mt6360_resume);
-static const struct of_device_id __maybe_unused mt6360_pmu_of_id[] = {
- { .compatible = "mediatek,mt6360_pmu", },
+static const struct of_device_id __maybe_unused mt6360_of_id[] = {
+ { .compatible = "mediatek,mt6360", },
{},
};
-MODULE_DEVICE_TABLE(of, mt6360_pmu_of_id);
+MODULE_DEVICE_TABLE(of, mt6360_of_id);
-static struct i2c_driver mt6360_pmu_driver = {
+static struct i2c_driver mt6360_driver = {
.driver = {
- .name = "mt6360_pmu",
- .pm = &mt6360_pmu_pm_ops,
- .of_match_table = of_match_ptr(mt6360_pmu_of_id),
+ .name = "mt6360",
+ .pm = &mt6360_pm_ops,
+ .of_match_table = of_match_ptr(mt6360_of_id),
},
- .probe_new = mt6360_pmu_probe,
+ .probe_new = mt6360_probe,
};
-module_i2c_driver(mt6360_pmu_driver);
+module_i2c_driver(mt6360_driver);
MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>");
-MODULE_DESCRIPTION("MT6360 PMU I2C Driver");
+MODULE_DESCRIPTION("MT6360 I2C Driver");
MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/mt6360.h b/include/linux/mfd/mt6360.h
deleted file mode 100644
index ea13040..0000000
--- a/include/linux/mfd/mt6360.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2020 MediaTek Inc.
- */
-
-#ifndef __MT6360_H__
-#define __MT6360_H__
-
-#include <linux/regmap.h>
-
-enum {
- MT6360_SLAVE_PMU = 0,
- MT6360_SLAVE_PMIC,
- MT6360_SLAVE_LDO,
- MT6360_SLAVE_TCPC,
- MT6360_SLAVE_MAX,
-};
-
-#define MT6360_PMU_SLAVEID (0x34)
-#define MT6360_PMIC_SLAVEID (0x1A)
-#define MT6360_LDO_SLAVEID (0x64)
-#define MT6360_TCPC_SLAVEID (0x4E)
-
-struct mt6360_pmu_data {
- struct i2c_client *i2c[MT6360_SLAVE_MAX];
- struct device *dev;
- struct regmap *regmap;
- struct regmap_irq_chip_data *irq_data;
- unsigned int chip_rev;
-};
-
-/* PMU register defininition */
-#define MT6360_PMU_DEV_INFO (0x00)
-#define MT6360_PMU_CORE_CTRL1 (0x01)
-#define MT6360_PMU_RST1 (0x02)
-#define MT6360_PMU_CRCEN (0x03)
-#define MT6360_PMU_RST_PAS_CODE1 (0x04)
-#define MT6360_PMU_RST_PAS_CODE2 (0x05)
-#define MT6360_PMU_CORE_CTRL2 (0x06)
-#define MT6360_PMU_TM_PAS_CODE1 (0x07)
-#define MT6360_PMU_TM_PAS_CODE2 (0x08)
-#define MT6360_PMU_TM_PAS_CODE3 (0x09)
-#define MT6360_PMU_TM_PAS_CODE4 (0x0A)
-#define MT6360_PMU_IRQ_IND (0x0B)
-#define MT6360_PMU_IRQ_MASK (0x0C)
-#define MT6360_PMU_IRQ_SET (0x0D)
-#define MT6360_PMU_SHDN_CTRL (0x0E)
-#define MT6360_PMU_TM_INF (0x0F)
-#define MT6360_PMU_I2C_CTRL (0x10)
-#define MT6360_PMU_CHG_CTRL1 (0x11)
-#define MT6360_PMU_CHG_CTRL2 (0x12)
-#define MT6360_PMU_CHG_CTRL3 (0x13)
-#define MT6360_PMU_CHG_CTRL4 (0x14)
-#define MT6360_PMU_CHG_CTRL5 (0x15)
-#define MT6360_PMU_CHG_CTRL6 (0x16)
-#define MT6360_PMU_CHG_CTRL7 (0x17)
-#define MT6360_PMU_CHG_CTRL8 (0x18)
-#define MT6360_PMU_CHG_CTRL9 (0x19)
-#define MT6360_PMU_CHG_CTRL10 (0x1A)
-#define MT6360_PMU_CHG_CTRL11 (0x1B)
-#define MT6360_PMU_CHG_CTRL12 (0x1C)
-#define MT6360_PMU_CHG_CTRL13 (0x1D)
-#define MT6360_PMU_CHG_CTRL14 (0x1E)
-#define MT6360_PMU_CHG_CTRL15 (0x1F)
-#define MT6360_PMU_CHG_CTRL16 (0x20)
-#define MT6360_PMU_CHG_AICC_RESULT (0x21)
-#define MT6360_PMU_DEVICE_TYPE (0x22)
-#define MT6360_PMU_QC_CONTROL1 (0x23)
-#define MT6360_PMU_QC_CONTROL2 (0x24)
-#define MT6360_PMU_QC30_CONTROL1 (0x25)
-#define MT6360_PMU_QC30_CONTROL2 (0x26)
-#define MT6360_PMU_USB_STATUS1 (0x27)
-#define MT6360_PMU_QC_STATUS1 (0x28)
-#define MT6360_PMU_QC_STATUS2 (0x29)
-#define MT6360_PMU_CHG_PUMP (0x2A)
-#define MT6360_PMU_CHG_CTRL17 (0x2B)
-#define MT6360_PMU_CHG_CTRL18 (0x2C)
-#define MT6360_PMU_CHRDET_CTRL1 (0x2D)
-#define MT6360_PMU_CHRDET_CTRL2 (0x2E)
-#define MT6360_PMU_DPDN_CTRL (0x2F)
-#define MT6360_PMU_CHG_HIDDEN_CTRL1 (0x30)
-#define MT6360_PMU_CHG_HIDDEN_CTRL2 (0x31)
-#define MT6360_PMU_CHG_HIDDEN_CTRL3 (0x32)
-#define MT6360_PMU_CHG_HIDDEN_CTRL4 (0x33)
-#define MT6360_PMU_CHG_HIDDEN_CTRL5 (0x34)
-#define MT6360_PMU_CHG_HIDDEN_CTRL6 (0x35)
-#define MT6360_PMU_CHG_HIDDEN_CTRL7 (0x36)
-#define MT6360_PMU_CHG_HIDDEN_CTRL8 (0x37)
-#define MT6360_PMU_CHG_HIDDEN_CTRL9 (0x38)
-#define MT6360_PMU_CHG_HIDDEN_CTRL10 (0x39)
-#define MT6360_PMU_CHG_HIDDEN_CTRL11 (0x3A)
-#define MT6360_PMU_CHG_HIDDEN_CTRL12 (0x3B)
-#define MT6360_PMU_CHG_HIDDEN_CTRL13 (0x3C)
-#define MT6360_PMU_CHG_HIDDEN_CTRL14 (0x3D)
-#define MT6360_PMU_CHG_HIDDEN_CTRL15 (0x3E)
-#define MT6360_PMU_CHG_HIDDEN_CTRL16 (0x3F)
-#define MT6360_PMU_CHG_HIDDEN_CTRL17 (0x40)
-#define MT6360_PMU_CHG_HIDDEN_CTRL18 (0x41)
-#define MT6360_PMU_CHG_HIDDEN_CTRL19 (0x42)
-#define MT6360_PMU_CHG_HIDDEN_CTRL20 (0x43)
-#define MT6360_PMU_CHG_HIDDEN_CTRL21 (0x44)
-#define MT6360_PMU_CHG_HIDDEN_CTRL22 (0x45)
-#define MT6360_PMU_CHG_HIDDEN_CTRL23 (0x46)
-#define MT6360_PMU_CHG_HIDDEN_CTRL24 (0x47)
-#define MT6360_PMU_CHG_HIDDEN_CTRL25 (0x48)
-#define MT6360_PMU_BC12_CTRL (0x49)
-#define MT6360_PMU_CHG_STAT (0x4A)
-#define MT6360_PMU_RESV1 (0x4B)
-#define MT6360_PMU_TYPEC_OTP_TH_SEL_CODEH (0x4E)
-#define MT6360_PMU_TYPEC_OTP_TH_SEL_CODEL (0x4F)
-#define MT6360_PMU_TYPEC_OTP_HYST_TH (0x50)
-#define MT6360_PMU_TYPEC_OTP_CTRL (0x51)
-#define MT6360_PMU_ADC_BAT_DATA_H (0x52)
-#define MT6360_PMU_ADC_BAT_DATA_L (0x53)
-#define MT6360_PMU_IMID_BACKBST_ON (0x54)
-#define MT6360_PMU_IMID_BACKBST_OFF (0x55)
-#define MT6360_PMU_ADC_CONFIG (0x56)
-#define MT6360_PMU_ADC_EN2 (0x57)
-#define MT6360_PMU_ADC_IDLE_T (0x58)
-#define MT6360_PMU_ADC_RPT_1 (0x5A)
-#define MT6360_PMU_ADC_RPT_2 (0x5B)
-#define MT6360_PMU_ADC_RPT_3 (0x5C)
-#define MT6360_PMU_ADC_RPT_ORG1 (0x5D)
-#define MT6360_PMU_ADC_RPT_ORG2 (0x5E)
-#define MT6360_PMU_BAT_OVP_TH_SEL_CODEH (0x5F)
-#define MT6360_PMU_BAT_OVP_TH_SEL_CODEL (0x60)
-#define MT6360_PMU_CHG_CTRL19 (0x61)
-#define MT6360_PMU_VDDASUPPLY (0x62)
-#define MT6360_PMU_BC12_MANUAL (0x63)
-#define MT6360_PMU_CHGDET_FUNC (0x64)
-#define MT6360_PMU_FOD_CTRL (0x65)
-#define MT6360_PMU_CHG_CTRL20 (0x66)
-#define MT6360_PMU_CHG_HIDDEN_CTRL26 (0x67)
-#define MT6360_PMU_CHG_HIDDEN_CTRL27 (0x68)
-#define MT6360_PMU_RESV2 (0x69)
-#define MT6360_PMU_USBID_CTRL1 (0x6D)
-#define MT6360_PMU_USBID_CTRL2 (0x6E)
-#define MT6360_PMU_USBID_CTRL3 (0x6F)
-#define MT6360_PMU_FLED_CFG (0x70)
-#define MT6360_PMU_RESV3 (0x71)
-#define MT6360_PMU_FLED1_CTRL (0x72)
-#define MT6360_PMU_FLED_STRB_CTRL (0x73)
-#define MT6360_PMU_FLED1_STRB_CTRL2 (0x74)
-#define MT6360_PMU_FLED1_TOR_CTRL (0x75)
-#define MT6360_PMU_FLED2_CTRL (0x76)
-#define MT6360_PMU_RESV4 (0x77)
-#define MT6360_PMU_FLED2_STRB_CTRL2 (0x78)
-#define MT6360_PMU_FLED2_TOR_CTRL (0x79)
-#define MT6360_PMU_FLED_VMIDTRK_CTRL1 (0x7A)
-#define MT6360_PMU_FLED_VMID_RTM (0x7B)
-#define MT6360_PMU_FLED_VMIDTRK_CTRL2 (0x7C)
-#define MT6360_PMU_FLED_PWSEL (0x7D)
-#define MT6360_PMU_FLED_EN (0x7E)
-#define MT6360_PMU_FLED_Hidden1 (0x7F)
-#define MT6360_PMU_RGB_EN (0x80)
-#define MT6360_PMU_RGB1_ISNK (0x81)
-#define MT6360_PMU_RGB2_ISNK (0x82)
-#define MT6360_PMU_RGB3_ISNK (0x83)
-#define MT6360_PMU_RGB_ML_ISNK (0x84)
-#define MT6360_PMU_RGB1_DIM (0x85)
-#define MT6360_PMU_RGB2_DIM (0x86)
-#define MT6360_PMU_RGB3_DIM (0x87)
-#define MT6360_PMU_RESV5 (0x88)
-#define MT6360_PMU_RGB12_Freq (0x89)
-#define MT6360_PMU_RGB34_Freq (0x8A)
-#define MT6360_PMU_RGB1_Tr (0x8B)
-#define MT6360_PMU_RGB1_Tf (0x8C)
-#define MT6360_PMU_RGB1_TON_TOFF (0x8D)
-#define MT6360_PMU_RGB2_Tr (0x8E)
-#define MT6360_PMU_RGB2_Tf (0x8F)
-#define MT6360_PMU_RGB2_TON_TOFF (0x90)
-#define MT6360_PMU_RGB3_Tr (0x91)
-#define MT6360_PMU_RGB3_Tf (0x92)
-#define MT6360_PMU_RGB3_TON_TOFF (0x93)
-#define MT6360_PMU_RGB_Hidden_CTRL1 (0x94)
-#define MT6360_PMU_RGB_Hidden_CTRL2 (0x95)
-#define MT6360_PMU_RESV6 (0x97)
-#define MT6360_PMU_SPARE1 (0x9A)
-#define MT6360_PMU_SPARE2 (0xA0)
-#define MT6360_PMU_SPARE3 (0xB0)
-#define MT6360_PMU_SPARE4 (0xC0)
-#define MT6360_PMU_CHG_IRQ1 (0xD0)
-#define MT6360_PMU_CHG_IRQ2 (0xD1)
-#define MT6360_PMU_CHG_IRQ3 (0xD2)
-#define MT6360_PMU_CHG_IRQ4 (0xD3)
-#define MT6360_PMU_CHG_IRQ5 (0xD4)
-#define MT6360_PMU_CHG_IRQ6 (0xD5)
-#define MT6360_PMU_QC_IRQ (0xD6)
-#define MT6360_PMU_FOD_IRQ (0xD7)
-#define MT6360_PMU_BASE_IRQ (0xD8)
-#define MT6360_PMU_FLED_IRQ1 (0xD9)
-#define MT6360_PMU_FLED_IRQ2 (0xDA)
-#define MT6360_PMU_RGB_IRQ (0xDB)
-#define MT6360_PMU_BUCK1_IRQ (0xDC)
-#define MT6360_PMU_BUCK2_IRQ (0xDD)
-#define MT6360_PMU_LDO_IRQ1 (0xDE)
-#define MT6360_PMU_LDO_IRQ2 (0xDF)
-#define MT6360_PMU_CHG_STAT1 (0xE0)
-#define MT6360_PMU_CHG_STAT2 (0xE1)
-#define MT6360_PMU_CHG_STAT3 (0xE2)
-#define MT6360_PMU_CHG_STAT4 (0xE3)
-#define MT6360_PMU_CHG_STAT5 (0xE4)
-#define MT6360_PMU_CHG_STAT6 (0xE5)
-#define MT6360_PMU_QC_STAT (0xE6)
-#define MT6360_PMU_FOD_STAT (0xE7)
-#define MT6360_PMU_BASE_STAT (0xE8)
-#define MT6360_PMU_FLED_STAT1 (0xE9)
-#define MT6360_PMU_FLED_STAT2 (0xEA)
-#define MT6360_PMU_RGB_STAT (0xEB)
-#define MT6360_PMU_BUCK1_STAT (0xEC)
-#define MT6360_PMU_BUCK2_STAT (0xED)
-#define MT6360_PMU_LDO_STAT1 (0xEE)
-#define MT6360_PMU_LDO_STAT2 (0xEF)
-#define MT6360_PMU_CHG_MASK1 (0xF0)
-#define MT6360_PMU_CHG_MASK2 (0xF1)
-#define MT6360_PMU_CHG_MASK3 (0xF2)
-#define MT6360_PMU_CHG_MASK4 (0xF3)
-#define MT6360_PMU_CHG_MASK5 (0xF4)
-#define MT6360_PMU_CHG_MASK6 (0xF5)
-#define MT6360_PMU_QC_MASK (0xF6)
-#define MT6360_PMU_FOD_MASK (0xF7)
-#define MT6360_PMU_BASE_MASK (0xF8)
-#define MT6360_PMU_FLED_MASK1 (0xF9)
-#define MT6360_PMU_FLED_MASK2 (0xFA)
-#define MT6360_PMU_FAULTB_MASK (0xFB)
-#define MT6360_PMU_BUCK1_MASK (0xFC)
-#define MT6360_PMU_BUCK2_MASK (0xFD)
-#define MT6360_PMU_LDO_MASK1 (0xFE)
-#define MT6360_PMU_LDO_MASK2 (0xFF)
-#define MT6360_PMU_MAXREG (MT6360_PMU_LDO_MASK2)
-
-/* MT6360_PMU_IRQ_SET */
-#define MT6360_PMU_IRQ_REGNUM (MT6360_PMU_LDO_IRQ2 - MT6360_PMU_CHG_IRQ1 + 1)
-#define MT6360_IRQ_RETRIG BIT(2)
-
-#define CHIP_VEN_MASK (0xF0)
-#define CHIP_VEN_MT6360 (0x50)
-#define CHIP_REV_MASK (0x0F)
-
-#endif /* __MT6360_H__ */
--
2.7.4
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 3/4] iio: adc: mt6360: Add ADC driver for MT6360
2020-06-19 11:53 [PATCH v2 0/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 Gene Chen
2020-06-19 11:53 ` [PATCH v2 1/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 PMIC Gene Chen
2020-06-19 11:53 ` [PATCH v2 2/4] mfd: mt6360: implement i2c R/W with CRC Gene Chen
@ 2020-06-19 11:53 ` Gene Chen
2020-06-20 17:03 ` Jonathan Cameron
2020-06-19 11:53 ` [PATCH v2 4/4] regulator: mt6360: Add support for MT6360 regulator Gene Chen
2020-06-20 16:55 ` [PATCH v2 0/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 Jonathan Cameron
4 siblings, 1 reply; 10+ messages in thread
From: Gene Chen @ 2020-06-19 11:53 UTC (permalink / raw)
To: lee.jones, jic23, jacek.anaszewski, pavel, matthias.bgg
Cc: gene_chen, lars, lgirdwood, linux-kernel, cy_huang,
benjamin.chao, broonie, linux-mediatek, dmurphy, pmeerw,
knaack.h, linux-arm-kernel, shufan_lee
From: Gene Chen <gene_chen@richtek.com>
Add MT6360 ADC driver include Charger Current, Voltage, and
Temperature.
Signed-off-by: Gene Chen <gene_chen@richtek.com>
---
drivers/iio/adc/Kconfig | 11 ++
drivers/iio/adc/Makefile | 1 +
drivers/iio/adc/mt6360-adc.c | 388 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 400 insertions(+)
create mode 100644 drivers/iio/adc/mt6360-adc.c
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index ff35696..7c77424 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -702,6 +702,17 @@ config MCP3911
This driver can also be built as a module. If so, the module will be
called mcp3911.
+config MEDIATEK_MT6360_ADC
+ tristate "Mediatek MT6360 ADC Part"
+ depends on MFD_MT6360
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say Y here to enable MT6360 ADC Part.
+ Integrated for System Monitoring include
+ Charger and Battery Current, Voltage and
+ Temperature
+
config MEDIATEK_MT6577_AUXADC
tristate "MediaTek AUXADC driver"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 90f94ad..5fca90a 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MAX9611) += max9611.o
obj-$(CONFIG_MCP320X) += mcp320x.o
obj-$(CONFIG_MCP3422) += mcp3422.o
obj-$(CONFIG_MCP3911) += mcp3911.o
+obj-$(CONFIG_MEDIATEK_MT6360_ADC) += mt6360-adc.o
obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o
obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
diff --git a/drivers/iio/adc/mt6360-adc.c b/drivers/iio/adc/mt6360-adc.c
new file mode 100644
index 0000000..a8ca80d
--- /dev/null
+++ b/drivers/iio/adc/mt6360-adc.c
@@ -0,0 +1,388 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ *
+ * Author: Gene Chen <gene_chen@richtek.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/ktime.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+
+#define MT6360_REG_PMUCHGCTRL3 0x313
+#define MT6360_REG_PMUADCCFG 0x356
+#define MT6360_REG_PMUADCRPT1 0x35A
+
+/* PMUCHGCTRL3 0x313 */
+#define MT6360_AICR_MASK 0xFC
+#define MT6360_AICR_SHFT 2
+#define MT6360_AICR_400MA 0x6
+/* PMUADCCFG 0x356 */
+#define MT6360_ADCEN_MASK 0x8000
+/* PMUADCRPT1 0x35A */
+#define MT6360_PREFERCH_MASK 0xF0
+#define MT6360_PREFERCH_SHFT 4
+#define MT6360_RPTCH_MASK 0x0F
+
+enum {
+ MT6360_CHAN_USBID = 0,
+ MT6360_CHAN_VBUSDIV5,
+ MT6360_CHAN_VBUSDIV2,
+ MT6360_CHAN_VSYS,
+ MT6360_CHAN_VBAT,
+ MT6360_CHAN_IBUS,
+ MT6360_CHAN_IBAT,
+ MT6360_CHAN_CHG_VDDP,
+ MT6360_CHAN_TEMP_JC,
+ MT6360_CHAN_VREF_TS,
+ MT6360_CHAN_TS,
+ MT6360_CHAN_MAX,
+};
+
+struct mt6360_adc_data {
+ struct device *dev;
+ struct regmap *regmap;
+ struct completion adc_complete;
+ struct mutex adc_lock;
+ ktime_t last_off_timestamps[MT6360_CHAN_MAX];
+ int irq;
+};
+
+static inline int mt6360_adc_val_converter(int val, int multiplier,
+ int offset, int divisor)
+{
+ return ((val * multiplier) + offset) / divisor;
+}
+
+static int mt6360_adc_convert_processed_val(struct mt6360_adc_data *info,
+ int chan_idx, int *val)
+{
+ unsigned int regval = 0;
+ const struct converter {
+ int multiplier;
+ int offset;
+ int divisor;
+ } adc_converter[MT6360_CHAN_MAX] = {
+ { 1250, 0, 1}, /* USBID */
+ { 6250, 0, 1}, /* VBUSDIV5 */
+ { 2500, 0, 1}, /* VBUSDIV2 */
+ { 1250, 0, 1}, /* VSYS */
+ { 1250, 0, 1}, /* VBAT */
+ { 2500, 0, 1}, /* IBUS */
+ { 2500, 0, 1}, /* IBAT */
+ { 1250, 0, 1}, /* CHG_VDDP */
+ { 105, -8000, 100}, /* TEMP_JC */
+ { 1250, 0, 1}, /* VREF_TS */
+ { 1250, 0, 1}, /* TS */
+ }, sp_ibus_adc_converter = { 1900, 0, 1 }, *sel_converter;
+ int ret;
+
+ sel_converter = adc_converter + chan_idx;
+ if (chan_idx == MT6360_CHAN_IBUS) {
+ /* ibus chan will be affected by aicr config */
+ /* if aicr < 400, apply the special ibus converter */
+ ret = regmap_read(info->regmap,
+ MT6360_REG_PMUCHGCTRL3, ®val);
+ if (ret)
+ return ret;
+
+ regval = (regval & MT6360_AICR_MASK) >> MT6360_AICR_SHFT;
+ if (regval < MT6360_AICR_400MA)
+ sel_converter = &sp_ibus_adc_converter;
+ }
+
+ *val = mt6360_adc_val_converter(*val, sel_converter->multiplier,
+ sel_converter->offset,
+ sel_converter->divisor);
+
+ return 0;
+}
+
+static int mt6360_adc_read_processed(struct mt6360_adc_data *mad,
+ int channel, int *val)
+{
+ u16 adc_enable;
+ u8 rpt[3];
+ ktime_t start_t, predict_end_t;
+ long timeout;
+ int value, ret;
+
+ mutex_lock(&mad->adc_lock);
+
+ /* select preferred channel that we want */
+ ret = regmap_update_bits(mad->regmap,
+ MT6360_REG_PMUADCRPT1, MT6360_PREFERCH_MASK,
+ channel << MT6360_PREFERCH_SHFT);
+ if (ret)
+ goto out_adc;
+
+ /* enable adc channel we want and adc_en */
+ adc_enable = MT6360_ADCEN_MASK | BIT(channel);
+ adc_enable = cpu_to_be16(adc_enable);
+ ret = regmap_raw_write(mad->regmap, MT6360_REG_PMUADCCFG,
+ (void *)&adc_enable, sizeof(u16));
+ if (ret)
+ goto out_adc;
+
+ start_t = ktime_get();
+ predict_end_t = ktime_add_ms(mad->last_off_timestamps[channel], 50);
+
+ if (ktime_after(start_t, predict_end_t))
+ predict_end_t = ktime_add_ms(start_t, 25);
+ else
+ predict_end_t = ktime_add_ms(start_t, 75);
+
+ enable_irq(mad->irq);
+adc_retry:
+ reinit_completion(&mad->adc_complete);
+
+ /* wait for conversion to complete */
+ timeout = wait_for_completion_timeout(&mad->adc_complete,
+ msecs_to_jiffies(200));
+ if (timeout == 0) {
+ ret = -ETIMEDOUT;
+ goto out_adc_conv;
+ } else if (timeout < 0) {
+ ret = -EINTR;
+ goto out_adc_conv;
+ }
+
+ ret = regmap_raw_read(mad->regmap,
+ MT6360_REG_PMUADCRPT1, rpt, sizeof(rpt));
+ if (ret)
+ goto out_adc_conv;
+
+ /* check the current reported channel */
+ if ((rpt[0] & MT6360_RPTCH_MASK) != channel) {
+ dev_dbg(mad->dev,
+ "not wanted channel report [%02x]\n", rpt[0]);
+ goto adc_retry;
+ }
+
+ if (!ktime_after(ktime_get(), predict_end_t)) {
+ dev_dbg(mad->dev, "time is not after one adc_conv_t\n");
+ goto adc_retry;
+ }
+
+ value = (rpt[1] << 8) | rpt[2];
+
+ ret = mt6360_adc_convert_processed_val(mad, channel, &value);
+ if (ret)
+ goto out_adc_conv;
+
+ *val = value;
+ ret = IIO_VAL_INT;
+
+out_adc_conv:
+ disable_irq(mad->irq);
+ adc_enable = MT6360_ADCEN_MASK;
+ adc_enable = cpu_to_be16(adc_enable);
+ regmap_raw_write(mad->regmap, MT6360_REG_PMUADCCFG,
+ (void *)&adc_enable, sizeof(u16));
+ mad->last_off_timestamps[channel] = ktime_get();
+ /* set prefer channel to 0xf */
+ regmap_update_bits(mad->regmap, MT6360_REG_PMUADCRPT1,
+ MT6360_PREFERCH_MASK, 0xF << MT6360_PREFERCH_SHFT);
+out_adc:
+ mutex_unlock(&mad->adc_lock);
+
+ return ret;
+}
+
+static int mt6360_adc_read_raw(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long mask)
+{
+ struct mt6360_adc_data *mad = iio_priv(iio_dev);
+
+ if (mask == IIO_CHAN_INFO_PROCESSED)
+ return mt6360_adc_read_processed(mad, chan->channel, val);
+
+ return -EINVAL;
+}
+
+static const struct iio_info mt6360_adc_iio_info = {
+ .read_raw = mt6360_adc_read_raw,
+};
+
+#define MT6360_ADC_CHAN(_idx, _type) { \
+ .type = _type, \
+ .channel = MT6360_CHAN_##_idx, \
+ .scan_index = MT6360_CHAN_##_idx, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 32, \
+ .storagebits = 32, \
+ .shift = 0, \
+ .endianness = IIO_CPU, \
+ }, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+ .extend_name = #_idx, \
+ .datasheet_name = #_idx, \
+ .indexed = 1, \
+}
+
+static const struct iio_chan_spec mt6360_adc_channels[] = {
+ MT6360_ADC_CHAN(USBID, IIO_VOLTAGE),
+ MT6360_ADC_CHAN(VBUSDIV5, IIO_VOLTAGE),
+ MT6360_ADC_CHAN(VBUSDIV2, IIO_VOLTAGE),
+ MT6360_ADC_CHAN(VSYS, IIO_VOLTAGE),
+ MT6360_ADC_CHAN(VBAT, IIO_VOLTAGE),
+ MT6360_ADC_CHAN(IBUS, IIO_CURRENT),
+ MT6360_ADC_CHAN(IBAT, IIO_CURRENT),
+ MT6360_ADC_CHAN(CHG_VDDP, IIO_VOLTAGE),
+ MT6360_ADC_CHAN(TEMP_JC, IIO_TEMP),
+ MT6360_ADC_CHAN(VREF_TS, IIO_VOLTAGE),
+ MT6360_ADC_CHAN(TS, IIO_VOLTAGE),
+ IIO_CHAN_SOFT_TIMESTAMP(MT6360_CHAN_MAX),
+};
+
+static irqreturn_t mt6360_pmu_adc_donei_handler(int irq, void *data)
+{
+ struct mt6360_adc_data *mad = iio_priv(data);
+
+ complete(&mad->adc_complete);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mt6360_adc_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ /* 11 ch s32 numbers + 1 s64 timestamp */
+ s32 data[MT6360_CHAN_MAX + 2] = { };
+ int i = 0, bit, val, ret;
+
+ for_each_set_bit(bit,
+ indio_dev->active_scan_mask, indio_dev->masklength) {
+ const struct iio_chan_spec *chan = indio_dev->channels + bit;
+
+ ret = mt6360_adc_read_raw(indio_dev, chan, &val,
+ NULL, IIO_CHAN_INFO_PROCESSED);
+ if (ret != IIO_VAL_INT) {
+ dev_warn(&indio_dev->dev,
+ "Failed to get %d conversion val\n", bit);
+ goto out;
+ }
+
+ data[i++] = val;
+ }
+ iio_push_to_buffers_with_timestamp(indio_dev,
+ data, iio_get_time_ns(indio_dev));
+out:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static inline int mt6360_adc_reset(struct mt6360_adc_data *info)
+{
+ u8 configs[3] = {0x80, 0, 0};
+ ktime_t all_off_time;
+ int i;
+
+ all_off_time = ktime_get();
+ for (i = 0; i < MT6360_CHAN_MAX; i++)
+ info->last_off_timestamps[i] = all_off_time;
+
+ /* enable adc_en, clear adc_chn_en/zcv_en/adc_wait_t/adc_idle_t */
+ return regmap_raw_write(info->regmap,
+ MT6360_REG_PMUADCCFG, configs, sizeof(configs));
+}
+
+static int mt6360_adc_probe(struct platform_device *pdev)
+{
+ struct mt6360_adc_data *mad;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*mad));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ mad = iio_priv(indio_dev);
+ mad->dev = &pdev->dev;
+ init_completion(&mad->adc_complete);
+ mutex_init(&mad->adc_lock);
+
+ mad->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!mad->regmap) {
+ dev_err(&pdev->dev, "Failed to get parent regmap\n");
+ return -ENODEV;
+ }
+
+ ret = mt6360_adc_reset(mad);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to reset adc\n");
+ return ret;
+ }
+
+ mad->irq = platform_get_irq_byname(pdev, "adc_donei");
+ if (mad->irq < 0) {
+ dev_err(&pdev->dev, "Failed to get adc_done irq\n");
+ return mad->irq;
+ }
+
+ irq_set_status_flags(mad->irq, IRQ_NOAUTOEN);
+ ret = devm_request_threaded_irq(&pdev->dev, mad->irq, NULL,
+ mt6360_pmu_adc_donei_handler,
+ IRQF_TRIGGER_NONE, "adc_donei",
+ indio_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register adc_done irq\n");
+ return ret;
+ }
+
+ indio_dev->name = dev_name(&pdev->dev);
+ indio_dev->dev.parent = &pdev->dev;
+ indio_dev->info = &mt6360_adc_iio_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = mt6360_adc_channels;
+ indio_dev->num_channels = ARRAY_SIZE(mt6360_adc_channels);
+
+ ret = devm_iio_triggered_buffer_setup(&pdev->dev, indio_dev, NULL,
+ mt6360_adc_trigger_handler, NULL);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to allocate iio trigger buffer\n");
+ return ret;
+ }
+
+ ret = devm_iio_device_register(&pdev->dev, indio_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register iio device\n");
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, indio_dev);
+
+ return 0;
+}
+
+static const struct of_device_id __maybe_unused mt6360_adc_of_id[] = {
+ { .compatible = "mediatek,mt6360-adc", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mt6360_adc_of_id);
+
+static struct platform_driver mt6360_adc_driver = {
+ .driver = {
+ .name = "mt6360-adc",
+ .of_match_table = mt6360_adc_of_id,
+ },
+ .probe = mt6360_adc_probe,
+};
+module_platform_driver(mt6360_adc_driver);
+
+MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>");
+MODULE_DESCRIPTION("MT6360 ADC Driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 4/4] regulator: mt6360: Add support for MT6360 regulator
2020-06-19 11:53 [PATCH v2 0/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 Gene Chen
` (2 preceding siblings ...)
2020-06-19 11:53 ` [PATCH v2 3/4] iio: adc: mt6360: Add ADC driver for MT6360 Gene Chen
@ 2020-06-19 11:53 ` Gene Chen
2020-06-20 16:55 ` [PATCH v2 0/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 Jonathan Cameron
4 siblings, 0 replies; 10+ messages in thread
From: Gene Chen @ 2020-06-19 11:53 UTC (permalink / raw)
To: lee.jones, jic23, jacek.anaszewski, pavel, matthias.bgg
Cc: gene_chen, lars, lgirdwood, linux-kernel, cy_huang,
benjamin.chao, broonie, linux-mediatek, dmurphy, pmeerw,
knaack.h, linux-arm-kernel, shufan_lee
From: Gene Chen <gene_chen@richtek.com>
Add MT6360 regulator driver include 2-channel buck and
6-channel ldo
Signed-off-by: Gene Chen <gene_chen@richtek.com>
---
drivers/regulator/Kconfig | 9 +
drivers/regulator/Makefile | 1 +
drivers/regulator/mt6360-regulator.c | 485 +++++++++++++++++++++++++++++++++++
3 files changed, 495 insertions(+)
create mode 100644 drivers/regulator/mt6360-regulator.c
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 8f677f5..9ae5711 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -691,6 +691,15 @@ config REGULATOR_MT6358
This driver supports the control of different power rails of device
through regulator interface.
+config REGULATOR_MT6360
+ tristate "MT6360 SubPMIC Regulator"
+ depends on MFD_MT6360
+ help
+ Say Y here to enable MT6360 regulator support.
+ This is support MT6360 PMIC/LDO part include
+ 2-channel buck with Thermal Shutdown and Overload Protection
+ 6-channel High PSRR and Low Dropout LDO.
+
config REGULATOR_MT6380
tristate "MediaTek MT6380 PMIC"
depends on MTK_PMIC_WRAP
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index e8f1633..7256457 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -86,6 +86,7 @@ obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
obj-$(CONFIG_REGULATOR_MT6358) += mt6358-regulator.o
+obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o
obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
diff --git a/drivers/regulator/mt6360-regulator.c b/drivers/regulator/mt6360-regulator.c
new file mode 100644
index 0000000..f3c8911
--- /dev/null
+++ b/drivers/regulator/mt6360-regulator.c
@@ -0,0 +1,485 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (c) 2020 MediaTek Inc.
+
+// Author: Gene Chen <gene_chen@richtek.com>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/version.h>
+
+#include <dt-bindings/mfd/mt6360.h>
+
+enum {
+ MT6360_REGULATOR_BUCK1 = 0,
+ MT6360_REGULATOR_BUCK2,
+ MT6360_REGULATOR_LDO6,
+ MT6360_REGULATOR_LDO7,
+ MT6360_REGULATOR_LDO1,
+ MT6360_REGULATOR_LDO2,
+ MT6360_REGULATOR_LDO3,
+ MT6360_REGULATOR_LDO5,
+ MT6360_REGULATOR_MAX,
+};
+
+struct mt6360_irq_mapping {
+ const char *name;
+ irq_handler_t handler;
+};
+
+struct mt6360_regulator_desc {
+ const struct regulator_desc desc;
+ unsigned int mode_reg;
+ unsigned int mode_mask;
+ unsigned int state_reg;
+ unsigned int state_mask;
+ const struct mt6360_irq_mapping *irq_tables;
+ int irq_table_size;
+};
+
+struct mt6360_regulator_data {
+ struct device *dev;
+ struct regmap *regmap;
+};
+
+static irqreturn_t mt6360_pgb_event_handler(int irq, void *data)
+{
+ struct regulator_dev *rdev = data;
+
+ regulator_notifier_call_chain(rdev, REGULATOR_EVENT_FAIL, NULL);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mt6360_oc_event_handler(int irq, void *data)
+{
+ struct regulator_dev *rdev = data;
+
+ regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_CURRENT, NULL);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mt6360_ov_event_handler(int irq, void *data)
+{
+ struct regulator_dev *rdev = data;
+
+ regulator_notifier_call_chain(rdev,
+ REGULATOR_EVENT_REGULATION_OUT, NULL);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mt6360_uv_event_handler(int irq, void *data)
+{
+ struct regulator_dev *rdev = data;
+
+ regulator_notifier_call_chain(rdev,
+ REGULATOR_EVENT_UNDER_VOLTAGE, NULL);
+ return IRQ_HANDLED;
+}
+
+static const struct mt6360_irq_mapping buck1_irq_tbls[] = {
+ { "buck1_pgb_evt", mt6360_pgb_event_handler },
+ { "buck1_oc_evt", mt6360_oc_event_handler },
+ { "buck1_ov_evt", mt6360_ov_event_handler },
+ { "buck1_uv_evt", mt6360_uv_event_handler },
+};
+
+static const struct mt6360_irq_mapping buck2_irq_tbls[] = {
+ { "buck2_pgb_evt", mt6360_pgb_event_handler },
+ { "buck2_oc_evt", mt6360_oc_event_handler },
+ { "buck2_ov_evt", mt6360_ov_event_handler },
+ { "buck2_uv_evt", mt6360_uv_event_handler },
+};
+
+static const struct mt6360_irq_mapping ldo6_irq_tbls[] = {
+ { "ldo6_pgb_evt", mt6360_pgb_event_handler },
+ { "ldo6_oc_evt", mt6360_oc_event_handler },
+};
+
+static const struct mt6360_irq_mapping ldo7_irq_tbls[] = {
+ { "ldo7_pgb_evt", mt6360_pgb_event_handler },
+ { "ldo7_oc_evt", mt6360_oc_event_handler },
+};
+
+static const struct mt6360_irq_mapping ldo1_irq_tbls[] = {
+ { "ldo1_pgb_evt", mt6360_pgb_event_handler },
+ { "ldo1_oc_evt", mt6360_oc_event_handler },
+};
+
+static const struct mt6360_irq_mapping ldo2_irq_tbls[] = {
+ { "ldo2_pgb_evt", mt6360_pgb_event_handler },
+ { "ldo2_oc_evt", mt6360_oc_event_handler },
+};
+
+static const struct mt6360_irq_mapping ldo3_irq_tbls[] = {
+ { "ldo3_pgb_evt", mt6360_pgb_event_handler },
+ { "ldo3_oc_evt", mt6360_oc_event_handler },
+};
+
+static const struct mt6360_irq_mapping ldo5_irq_tbls[] = {
+ { "ldo5_pgb_evt", mt6360_pgb_event_handler },
+ { "ldo5_oc_evt", mt6360_oc_event_handler },
+};
+
+static const struct linear_range buck_vout_ranges[] = {
+ REGULATOR_LINEAR_RANGE(300000, 0x00, 0xc7, 5000),
+ REGULATOR_LINEAR_RANGE(1300000, 0xc8, 0xff, 0),
+};
+
+static const struct linear_range ldo_vout_ranges1[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0x00, 0x09, 10000),
+ REGULATOR_LINEAR_RANGE(600000, 0x0a, 0x10, 0),
+ REGULATOR_LINEAR_RANGE(610000, 0x11, 0x19, 10000),
+ REGULATOR_LINEAR_RANGE(700000, 0x1a, 0x20, 0),
+ REGULATOR_LINEAR_RANGE(710000, 0x21, 0x29, 10000),
+ REGULATOR_LINEAR_RANGE(800000, 0x2a, 0x30, 0),
+ REGULATOR_LINEAR_RANGE(810000, 0x31, 0x39, 10000),
+ REGULATOR_LINEAR_RANGE(900000, 0x3a, 0x40, 0),
+ REGULATOR_LINEAR_RANGE(910000, 0x41, 0x49, 10000),
+ REGULATOR_LINEAR_RANGE(1000000, 0x4a, 0x50, 0),
+ REGULATOR_LINEAR_RANGE(1010000, 0x51, 0x59, 10000),
+ REGULATOR_LINEAR_RANGE(1100000, 0x5a, 0x60, 0),
+ REGULATOR_LINEAR_RANGE(1110000, 0x61, 0x69, 10000),
+ REGULATOR_LINEAR_RANGE(1200000, 0x6a, 0x70, 0),
+ REGULATOR_LINEAR_RANGE(1210000, 0x71, 0x79, 10000),
+ REGULATOR_LINEAR_RANGE(1300000, 0x7a, 0x80, 0),
+ REGULATOR_LINEAR_RANGE(1310000, 0x81, 0x89, 10000),
+ REGULATOR_LINEAR_RANGE(1400000, 0x8a, 0x90, 0),
+ REGULATOR_LINEAR_RANGE(1410000, 0x91, 0x99, 10000),
+ REGULATOR_LINEAR_RANGE(1500000, 0x9a, 0xa0, 0),
+ REGULATOR_LINEAR_RANGE(1510000, 0xa1, 0xa9, 10000),
+ REGULATOR_LINEAR_RANGE(1600000, 0xaa, 0xb0, 0),
+ REGULATOR_LINEAR_RANGE(1610000, 0xb1, 0xb9, 10000),
+ REGULATOR_LINEAR_RANGE(1700000, 0xba, 0xc0, 0),
+ REGULATOR_LINEAR_RANGE(1710000, 0xc1, 0xc9, 10000),
+ REGULATOR_LINEAR_RANGE(1800000, 0xca, 0xd0, 0),
+ REGULATOR_LINEAR_RANGE(1810000, 0xd1, 0xd9, 10000),
+ REGULATOR_LINEAR_RANGE(1900000, 0xda, 0xe0, 0),
+ REGULATOR_LINEAR_RANGE(1910000, 0xe1, 0xe9, 10000),
+ REGULATOR_LINEAR_RANGE(2000000, 0xea, 0xf0, 0),
+ REGULATOR_LINEAR_RANGE(2010000, 0xf1, 0xf9, 10000),
+ REGULATOR_LINEAR_RANGE(2100000, 0xfa, 0xff, 0),
+};
+
+static const struct linear_range ldo_vout_ranges2[] = {
+ REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x09, 10000),
+ REGULATOR_LINEAR_RANGE(1300000, 0x0a, 0x10, 0),
+ REGULATOR_LINEAR_RANGE(1310000, 0x11, 0x19, 10000),
+ REGULATOR_LINEAR_RANGE(1400000, 0x1a, 0x1f, 0),
+ REGULATOR_LINEAR_RANGE(1500000, 0x20, 0x29, 10000),
+ REGULATOR_LINEAR_RANGE(1600000, 0x2a, 0x2f, 0),
+ REGULATOR_LINEAR_RANGE(1700000, 0x30, 0x39, 10000),
+ REGULATOR_LINEAR_RANGE(1800000, 0x3a, 0x40, 0),
+ REGULATOR_LINEAR_RANGE(1810000, 0x41, 0x49, 10000),
+ REGULATOR_LINEAR_RANGE(1900000, 0x4a, 0x4f, 0),
+ REGULATOR_LINEAR_RANGE(2000000, 0x50, 0x59, 10000),
+ REGULATOR_LINEAR_RANGE(2100000, 0x5a, 0x60, 0),
+ REGULATOR_LINEAR_RANGE(2110000, 0x61, 0x69, 10000),
+ REGULATOR_LINEAR_RANGE(2200000, 0x6a, 0x6f, 0),
+ REGULATOR_LINEAR_RANGE(2500000, 0x70, 0x79, 10000),
+ REGULATOR_LINEAR_RANGE(2600000, 0x7a, 0x7f, 0),
+ REGULATOR_LINEAR_RANGE(2700000, 0x80, 0x89, 10000),
+ REGULATOR_LINEAR_RANGE(2800000, 0x8a, 0x90, 0),
+ REGULATOR_LINEAR_RANGE(2810000, 0x91, 0x99, 10000),
+ REGULATOR_LINEAR_RANGE(2900000, 0x9a, 0xa0, 0),
+ REGULATOR_LINEAR_RANGE(2910000, 0xa1, 0xa9, 10000),
+ REGULATOR_LINEAR_RANGE(3000000, 0xaa, 0xb0, 0),
+ REGULATOR_LINEAR_RANGE(3010000, 0xb1, 0xb9, 10000),
+ REGULATOR_LINEAR_RANGE(3100000, 0xba, 0xc0, 0),
+ REGULATOR_LINEAR_RANGE(3110000, 0xc1, 0xc9, 10000),
+ REGULATOR_LINEAR_RANGE(3200000, 0xca, 0xcf, 0),
+ REGULATOR_LINEAR_RANGE(3300000, 0xd0, 0xd9, 10000),
+ REGULATOR_LINEAR_RANGE(3400000, 0xda, 0xe0, 0),
+ REGULATOR_LINEAR_RANGE(3410000, 0xe1, 0xe9, 10000),
+ REGULATOR_LINEAR_RANGE(3500000, 0xea, 0xf0, 0),
+ REGULATOR_LINEAR_RANGE(3510000, 0xf1, 0xf9, 10000),
+ REGULATOR_LINEAR_RANGE(3600000, 0xfa, 0xff, 0),
+};
+
+static const struct linear_range ldo_vout_ranges3[] = {
+ REGULATOR_LINEAR_RANGE(2700000, 0x00, 0x09, 10000),
+ REGULATOR_LINEAR_RANGE(2800000, 0x0a, 0x10, 0),
+ REGULATOR_LINEAR_RANGE(2810000, 0x11, 0x19, 10000),
+ REGULATOR_LINEAR_RANGE(2900000, 0x1a, 0x20, 0),
+ REGULATOR_LINEAR_RANGE(2910000, 0x21, 0x29, 10000),
+ REGULATOR_LINEAR_RANGE(3000000, 0x2a, 0x30, 0),
+ REGULATOR_LINEAR_RANGE(3010000, 0x31, 0x39, 10000),
+ REGULATOR_LINEAR_RANGE(3100000, 0x3a, 0x40, 0),
+ REGULATOR_LINEAR_RANGE(3110000, 0x41, 0x49, 10000),
+ REGULATOR_LINEAR_RANGE(3200000, 0x4a, 0x4f, 0),
+ REGULATOR_LINEAR_RANGE(3300000, 0x50, 0x59, 10000),
+ REGULATOR_LINEAR_RANGE(3400000, 0x5a, 0x60, 0),
+ REGULATOR_LINEAR_RANGE(3410000, 0x61, 0x69, 10000),
+ REGULATOR_LINEAR_RANGE(3500000, 0x6a, 0x70, 0),
+ REGULATOR_LINEAR_RANGE(3510000, 0x71, 0x79, 10000),
+ REGULATOR_LINEAR_RANGE(3600000, 0x7a, 0x7f, 0),
+};
+
+static int mt6360_regulator_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ const struct mt6360_regulator_desc *rdesc =
+ (const struct mt6360_regulator_desc *)rdev->desc;
+ struct regmap *regmap = rdev_get_regmap(rdev);
+ int shift = ffs(rdesc->mode_mask) - 1;
+ unsigned int val;
+ int ret;
+
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ val = MT6360_OPMODE_NORMAL;
+ break;
+ case REGULATOR_MODE_STANDBY:
+ val = MT6360_OPMODE_ULP;
+ break;
+ case REGULATOR_MODE_IDLE:
+ val = MT6360_OPMODE_LP;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_update_bits(regmap, rdesc->mode_reg,
+ rdesc->mode_mask, val << shift);
+ if (ret) {
+ dev_err(&rdev->dev, "%s: fail (%d)\n", __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static unsigned int mt6360_regulator_get_mode(struct regulator_dev *rdev)
+{
+ const struct mt6360_regulator_desc *rdesc =
+ (const struct mt6360_regulator_desc *)rdev->desc;
+ struct regmap *regmap = rdev_get_regmap(rdev);
+ int shift = ffs(rdesc->mode_mask) - 1;
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(regmap, rdesc->mode_reg, &val);
+ if (ret)
+ return ret;
+
+ val &= rdesc->mode_mask;
+ val >>= shift;
+
+ switch (val) {
+ case MT6360_OPMODE_LP:
+ return REGULATOR_MODE_IDLE;
+ case MT6360_OPMODE_ULP:
+ return REGULATOR_MODE_STANDBY;
+ case MT6360_OPMODE_NORMAL:
+ return REGULATOR_MODE_NORMAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mt6360_regulator_get_status(struct regulator_dev *rdev)
+{
+ const struct mt6360_regulator_desc *rdesc =
+ (const struct mt6360_regulator_desc *)rdev->desc;
+ struct regmap *regmap = rdev_get_regmap(rdev);
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(regmap, rdesc->state_reg, &val);
+ if (ret)
+ return ret;
+
+ if (val & rdesc->state_mask)
+ return REGULATOR_STATUS_ON;
+
+ return REGULATOR_STATUS_OFF;
+}
+
+static const struct regulator_ops mt6360_regulator_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_mode = mt6360_regulator_set_mode,
+ .get_mode = mt6360_regulator_get_mode,
+ .get_status = mt6360_regulator_get_status,
+};
+
+static unsigned int mt6360_regulator_of_map_mode(unsigned int hw_mode)
+{
+ switch (hw_mode) {
+ case MT6360_OPMODE_NORMAL:
+ return REGULATOR_MODE_NORMAL;
+ case MT6360_OPMODE_LP:
+ return REGULATOR_MODE_IDLE;
+ case MT6360_OPMODE_ULP:
+ return REGULATOR_MODE_STANDBY;
+ default:
+ return REGULATOR_MODE_INVALID;
+ }
+}
+
+#define MT6360_REGULATOR_DESC(_name, _sname, ereg, emask, vreg, vmask, \
+ mreg, mmask, streg, stmask, vranges, \
+ vcnts, offon_delay, irq_tbls) \
+{ \
+ .desc = { \
+ .name = #_name, \
+ .supply_name = #_sname, \
+ .id = MT6360_REGULATOR_##_name, \
+ .of_match = of_match_ptr(#_name), \
+ .of_map_mode = mt6360_regulator_of_map_mode, \
+ .owner = THIS_MODULE, \
+ .ops = &mt6360_regulator_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .vsel_reg = vreg, \
+ .vsel_mask = vmask, \
+ .enable_reg = ereg, \
+ .enable_mask = emask, \
+ .linear_ranges = vranges, \
+ .n_linear_ranges = ARRAY_SIZE(vranges), \
+ .n_voltages = vcnts, \
+ .off_on_delay = offon_delay, \
+ }, \
+ .mode_reg = mreg, \
+ .mode_mask = mmask, \
+ .state_reg = streg, \
+ .state_mask = stmask, \
+ .irq_tables = irq_tbls, \
+ .irq_table_size = ARRAY_SIZE(irq_tbls), \
+}
+
+static const struct mt6360_regulator_desc mt6360_regulator_descs[] = {
+ MT6360_REGULATOR_DESC(BUCK1, BUCK1_VIN, 0x117, 0x40, 0x110, 0xff, 0x117,
+ 0x30, 0x117, 0x04, buck_vout_ranges, 256, 0,
+ buck1_irq_tbls),
+ MT6360_REGULATOR_DESC(BUCK2, BUCK2_VIN, 0x127, 0x40, 0x120, 0xff, 0x127,
+ 0x30, 0x127, 0x04, buck_vout_ranges, 256, 0,
+ buck2_irq_tbls),
+ MT6360_REGULATOR_DESC(LDO6, LDO_VIN3, 0x137, 0x40, 0x13B, 0xff, 0x137,
+ 0x30, 0x137, 0x04, ldo_vout_ranges1, 256, 0,
+ ldo6_irq_tbls),
+ MT6360_REGULATOR_DESC(LDO7, LDO_VIN3, 0x131, 0x40, 0x135, 0xff, 0x131,
+ 0x30, 0x131, 0x04, ldo_vout_ranges1, 256, 0,
+ ldo7_irq_tbls),
+ MT6360_REGULATOR_DESC(LDO1, LDO_VIN1, 0x217, 0x40, 0x21B, 0xff, 0x217,
+ 0x30, 0x217, 0x04, ldo_vout_ranges2, 256, 0,
+ ldo1_irq_tbls),
+ MT6360_REGULATOR_DESC(LDO2, LDO_VIN1, 0x211, 0x40, 0x215, 0xff, 0x211,
+ 0x30, 0x211, 0x04, ldo_vout_ranges2, 256, 0,
+ ldo2_irq_tbls),
+ MT6360_REGULATOR_DESC(LDO3, LDO_VIN1, 0x205, 0x40, 0x209, 0xff, 0x205,
+ 0x30, 0x205, 0x04, ldo_vout_ranges2, 256, 100,
+ ldo3_irq_tbls),
+ MT6360_REGULATOR_DESC(LDO5, LDO_VIN2, 0x20B, 0x40, 0x20F, 0x7f, 0x20B,
+ 0x30, 0x20B, 0x04, ldo_vout_ranges3, 128, 100,
+ ldo5_irq_tbls),
+};
+
+static int mt6360_regulator_irq_register(struct platform_device *pdev,
+ struct regulator_dev *rdev,
+ const struct mt6360_irq_mapping *tbls,
+ int tbl_size)
+{
+ int i, irq, ret;
+
+ for (i = 0; i < tbl_size; i++) {
+ const struct mt6360_irq_mapping *irq_desc = tbls + i;
+
+ irq = platform_get_irq_byname(pdev, irq_desc->name);
+ if (irq < 0) {
+ dev_err(&pdev->dev,
+ "Fail to get %s irq\n", irq_desc->name);
+ return irq;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ irq_desc->handler,
+ IRQF_TRIGGER_NONE,
+ irq_desc->name,
+ rdev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Fail to request %s irq\n", irq_desc->name);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int mt6360_regulator_probe(struct platform_device *pdev)
+{
+ struct mt6360_regulator_data *mrd;
+ struct regulator_config config = {};
+ int i, ret;
+
+ mrd = devm_kzalloc(&pdev->dev, sizeof(*mrd), GFP_KERNEL);
+ if (!mrd)
+ return -ENOMEM;
+
+ mrd->dev = &pdev->dev;
+
+ mrd->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!mrd->regmap) {
+ dev_err(&pdev->dev, "Failed to get parent regmap\n");
+ return -ENODEV;
+ }
+
+ config.dev = &pdev->dev;
+ config.driver_data = mrd;
+ config.regmap = mrd->regmap;
+
+ for (i = 0; i < ARRAY_SIZE(mt6360_regulator_descs); i++) {
+ const struct mt6360_regulator_desc *rdesc =
+ mt6360_regulator_descs + i;
+ struct regulator_dev *rdev;
+
+ rdev = devm_regulator_register(&pdev->dev,
+ &rdesc->desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev,
+ "Failed to register %d regulaotr\n", i);
+ return PTR_ERR(rdev);
+ }
+
+ ret = mt6360_regulator_irq_register(pdev, rdev,
+ rdesc->irq_tables,
+ rdesc->irq_table_size);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to register %d regulaotr irqs\n", i);
+ return ret;
+ }
+ }
+
+ platform_set_drvdata(pdev, mrd);
+
+ return 0;
+}
+
+static const struct of_device_id __maybe_unused mt6360_regulator_of_id[] = {
+ { .compatible = "mediatek,mt6360-regulator", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mt6360_regulator_of_id);
+
+static struct platform_driver mt6360_regulator_driver = {
+ .driver = {
+ .name = "mt6360-regulator",
+ .of_match_table = mt6360_regulator_of_id,
+ },
+ .probe = mt6360_regulator_probe,
+};
+module_platform_driver(mt6360_regulator_driver);
+
+MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>");
+MODULE_DESCRIPTION("MT6360 Regulator Driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2 0/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360
2020-06-19 11:53 [PATCH v2 0/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 Gene Chen
` (3 preceding siblings ...)
2020-06-19 11:53 ` [PATCH v2 4/4] regulator: mt6360: Add support for MT6360 regulator Gene Chen
@ 2020-06-20 16:55 ` Jonathan Cameron
4 siblings, 0 replies; 10+ messages in thread
From: Jonathan Cameron @ 2020-06-20 16:55 UTC (permalink / raw)
To: Gene Chen
Cc: gene_chen, lars, pmeerw, lgirdwood, linux-kernel, cy_huang,
benjamin.chao, broonie, linux-mediatek, jacek.anaszewski, pavel,
knaack.h, matthias.bgg, shufan_lee, lee.jones, linux-arm-kernel,
dmurphy
On Fri, 19 Jun 2020 19:53:47 +0800
Gene Chen <gene.chen.richtek@gmail.com> wrote:
> This patch series add mt6360 sub-device adc/regulator and
> fix mfd architecture and add dt-binding document
Hi Gene
Please make sure you include linux-iio@vger.kernel.org in the cc list
for any iio related series. For now I'll take a quick look at the
ADC driver patch (and +cc the list for my reply)
Thanks,
Jonathan
>
> changelogs between v1 & v2
> - adjust binding document schema include mfd/adc/regulator
> - adc: use IIO_CHAN_INFO_PROCESSED only
> - adc: use devm_iio_triggered_buffer_setup
> - adc: use use s64 to record timestamp
> - regulator: merge regmap to mfd driver for r/w with crc
>
> Gene Chen (4)
> dt-bindings: mfd: Add bindings for the Mediatek MT6360
> mfd: mt6360: implement i2c R/W with CRC
> iio: adc: mt6360: Add ADC driver for MT6360
> regulator: mt6360: Add support for MT6360 regulator
>
> Documentation/devicetree/bindings/mfd/mt6360.txt | 122 +++++
> drivers/iio/adc/Kconfig | 11
> drivers/iio/adc/Makefile | 1
> drivers/iio/adc/mt6360-adc.c | 388 ++++++++++++++++
> drivers/mfd/Kconfig | 1
> drivers/mfd/mt6360-core.c | 541 +++++++++++++++--------
> drivers/regulator/Kconfig | 9
> drivers/regulator/Makefile | 1
> drivers/regulator/mt6360-regulator.c | 485 ++++++++++++++++++++
> include/dt-bindings/mfd/mt6360.h | 15
> include/linux/mfd/mt6360.h | 240 ----------
> 11 files changed, 1389 insertions(+), 425 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/mfd/mt6360.txt
> create mode 100644 include/dt-bindings/mfd/mt6360.h
> delete mode 100644 include/linux/mfd/mt6360.h
> create mode 100644 drivers/iio/adc/mt6360-adc.c
> create mode 100644 drivers/regulator/mt6360-regulator.c
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 3/4] iio: adc: mt6360: Add ADC driver for MT6360
2020-06-19 11:53 ` [PATCH v2 3/4] iio: adc: mt6360: Add ADC driver for MT6360 Gene Chen
@ 2020-06-20 17:03 ` Jonathan Cameron
0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Cameron @ 2020-06-20 17:03 UTC (permalink / raw)
To: Gene Chen
Cc: gene_chen, lars, pmeerw, linux-iio, lgirdwood, linux-kernel,
cy_huang, benjamin.chao, broonie, linux-mediatek,
jacek.anaszewski, pavel, knaack.h, matthias.bgg, shufan_lee,
lee.jones, linux-arm-kernel, dmurphy
On Fri, 19 Jun 2020 19:53:50 +0800
Gene Chen <gene.chen.richtek@gmail.com> wrote:
> From: Gene Chen <gene_chen@richtek.com>
>
> Add MT6360 ADC driver include Charger Current, Voltage, and
> Temperature.
>
> Signed-off-by: Gene Chen <gene_chen@richtek.com>
I've taken a quick look and highlighted a few things.
As mentioned in my reply to the cover letter please make sure to cc
the IIO mailing list. I'm far from the only person who might review
this driver and more to the point I look there first rather than
checking my personal email so you are bit lucky I noticed this today!
Jonathan
> ---
> drivers/iio/adc/Kconfig | 11 ++
> drivers/iio/adc/Makefile | 1 +
> drivers/iio/adc/mt6360-adc.c | 388 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 400 insertions(+)
> create mode 100644 drivers/iio/adc/mt6360-adc.c
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index ff35696..7c77424 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -702,6 +702,17 @@ config MCP3911
> This driver can also be built as a module. If so, the module will be
> called mcp3911.
>
> +config MEDIATEK_MT6360_ADC
> + tristate "Mediatek MT6360 ADC Part"
> + depends on MFD_MT6360
> + select IIO_BUFFER
> + select IIO_TRIGGERED_BUFFER
> + help
> + Say Y here to enable MT6360 ADC Part.
> + Integrated for System Monitoring include
> + Charger and Battery Current, Voltage and
> + Temperature
> +
> config MEDIATEK_MT6577_AUXADC
> tristate "MediaTek AUXADC driver"
> depends on ARCH_MEDIATEK || COMPILE_TEST
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 90f94ad..5fca90a 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -65,6 +65,7 @@ obj-$(CONFIG_MAX9611) += max9611.o
> obj-$(CONFIG_MCP320X) += mcp320x.o
> obj-$(CONFIG_MCP3422) += mcp3422.o
> obj-$(CONFIG_MCP3911) += mcp3911.o
> +obj-$(CONFIG_MEDIATEK_MT6360_ADC) += mt6360-adc.o
> obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o
> obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
> obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
> diff --git a/drivers/iio/adc/mt6360-adc.c b/drivers/iio/adc/mt6360-adc.c
> new file mode 100644
> index 0000000..a8ca80d
> --- /dev/null
> +++ b/drivers/iio/adc/mt6360-adc.c
> @@ -0,0 +1,388 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2020 MediaTek Inc.
> + *
> + * Author: Gene Chen <gene_chen@richtek.com>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/completion.h>
> +#include <linux/mutex.h>
> +#include <linux/regmap.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/ktime.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/triggered_buffer.h>
> +#include <linux/iio/trigger_consumer.h>
> +
> +#define MT6360_REG_PMUCHGCTRL3 0x313
> +#define MT6360_REG_PMUADCCFG 0x356
> +#define MT6360_REG_PMUADCRPT1 0x35A
> +
> +/* PMUCHGCTRL3 0x313 */
> +#define MT6360_AICR_MASK 0xFC
> +#define MT6360_AICR_SHFT 2
> +#define MT6360_AICR_400MA 0x6
> +/* PMUADCCFG 0x356 */
> +#define MT6360_ADCEN_MASK 0x8000
> +/* PMUADCRPT1 0x35A */
> +#define MT6360_PREFERCH_MASK 0xF0
> +#define MT6360_PREFERCH_SHFT 4
> +#define MT6360_RPTCH_MASK 0x0F
> +
> +enum {
> + MT6360_CHAN_USBID = 0,
> + MT6360_CHAN_VBUSDIV5,
> + MT6360_CHAN_VBUSDIV2,
> + MT6360_CHAN_VSYS,
> + MT6360_CHAN_VBAT,
> + MT6360_CHAN_IBUS,
> + MT6360_CHAN_IBAT,
> + MT6360_CHAN_CHG_VDDP,
> + MT6360_CHAN_TEMP_JC,
> + MT6360_CHAN_VREF_TS,
> + MT6360_CHAN_TS,
> + MT6360_CHAN_MAX,
> +};
> +
> +struct mt6360_adc_data {
> + struct device *dev;
> + struct regmap *regmap;
> + struct completion adc_complete;
> + struct mutex adc_lock;
> + ktime_t last_off_timestamps[MT6360_CHAN_MAX];
> + int irq;
> +};
> +
> +static inline int mt6360_adc_val_converter(int val, int multiplier,
> + int offset, int divisor)
> +{
> + return ((val * multiplier) + offset) / divisor;
> +}
> +
> +static int mt6360_adc_convert_processed_val(struct mt6360_adc_data *info,
> + int chan_idx, int *val)
> +{
> + unsigned int regval = 0;
> + const struct converter {
> + int multiplier;
> + int offset;
> + int divisor;
> + } adc_converter[MT6360_CHAN_MAX] = {
> + { 1250, 0, 1}, /* USBID */
> + { 6250, 0, 1}, /* VBUSDIV5 */
> + { 2500, 0, 1}, /* VBUSDIV2 */
> + { 1250, 0, 1}, /* VSYS */
> + { 1250, 0, 1}, /* VBAT */
> + { 2500, 0, 1}, /* IBUS */
> + { 2500, 0, 1}, /* IBAT */
> + { 1250, 0, 1}, /* CHG_VDDP */
> + { 105, -8000, 100}, /* TEMP_JC */
> + { 1250, 0, 1}, /* VREF_TS */
> + { 1250, 0, 1}, /* TS */
> + }, sp_ibus_adc_converter = { 1900, 0, 1 }, *sel_converter;
> + int ret;
> +
> + sel_converter = adc_converter + chan_idx;
> + if (chan_idx == MT6360_CHAN_IBUS) {
> + /* ibus chan will be affected by aicr config */
> + /* if aicr < 400, apply the special ibus converter */
> + ret = regmap_read(info->regmap,
> + MT6360_REG_PMUCHGCTRL3, ®val);
> + if (ret)
> + return ret;
> +
> + regval = (regval & MT6360_AICR_MASK) >> MT6360_AICR_SHFT;
> + if (regval < MT6360_AICR_400MA)
> + sel_converter = &sp_ibus_adc_converter;
> + }
> +
> + *val = mt6360_adc_val_converter(*val, sel_converter->multiplier,
> + sel_converter->offset,
> + sel_converter->divisor);
> +
> + return 0;
> +}
> +
> +static int mt6360_adc_read_processed(struct mt6360_adc_data *mad,
> + int channel, int *val)
> +{
> + u16 adc_enable;
> + u8 rpt[3];
> + ktime_t start_t, predict_end_t;
> + long timeout;
> + int value, ret;
> +
> + mutex_lock(&mad->adc_lock);
> +
> + /* select preferred channel that we want */
> + ret = regmap_update_bits(mad->regmap,
> + MT6360_REG_PMUADCRPT1, MT6360_PREFERCH_MASK,
> + channel << MT6360_PREFERCH_SHFT);
> + if (ret)
> + goto out_adc;
> +
> + /* enable adc channel we want and adc_en */
> + adc_enable = MT6360_ADCEN_MASK | BIT(channel);
> + adc_enable = cpu_to_be16(adc_enable);
> + ret = regmap_raw_write(mad->regmap, MT6360_REG_PMUADCCFG,
> + (void *)&adc_enable, sizeof(u16));
> + if (ret)
> + goto out_adc;
> +
> + start_t = ktime_get();
> + predict_end_t = ktime_add_ms(mad->last_off_timestamps[channel], 50);
> +
> + if (ktime_after(start_t, predict_end_t))
> + predict_end_t = ktime_add_ms(start_t, 25);
> + else
> + predict_end_t = ktime_add_ms(start_t, 75);
> +
> + enable_irq(mad->irq);
> +adc_retry:
> + reinit_completion(&mad->adc_complete);
> +
> + /* wait for conversion to complete */
> + timeout = wait_for_completion_timeout(&mad->adc_complete,
> + msecs_to_jiffies(200));
> + if (timeout == 0) {
> + ret = -ETIMEDOUT;
> + goto out_adc_conv;
> + } else if (timeout < 0) {
> + ret = -EINTR;
> + goto out_adc_conv;
> + }
> +
> + ret = regmap_raw_read(mad->regmap,
> + MT6360_REG_PMUADCRPT1, rpt, sizeof(rpt));
> + if (ret)
> + goto out_adc_conv;
> +
> + /* check the current reported channel */
> + if ((rpt[0] & MT6360_RPTCH_MASK) != channel) {
> + dev_dbg(mad->dev,
> + "not wanted channel report [%02x]\n", rpt[0]);
> + goto adc_retry;
> + }
> +
> + if (!ktime_after(ktime_get(), predict_end_t)) {
> + dev_dbg(mad->dev, "time is not after one adc_conv_t\n");
> + goto adc_retry;
> + }
> +
> + value = (rpt[1] << 8) | rpt[2];
> +
> + ret = mt6360_adc_convert_processed_val(mad, channel, &value);
> + if (ret)
> + goto out_adc_conv;
> +
> + *val = value;
> + ret = IIO_VAL_INT;
> +
> +out_adc_conv:
> + disable_irq(mad->irq);
> + adc_enable = MT6360_ADCEN_MASK;
> + adc_enable = cpu_to_be16(adc_enable);
> + regmap_raw_write(mad->regmap, MT6360_REG_PMUADCCFG,
> + (void *)&adc_enable, sizeof(u16));
> + mad->last_off_timestamps[channel] = ktime_get();
> + /* set prefer channel to 0xf */
> + regmap_update_bits(mad->regmap, MT6360_REG_PMUADCRPT1,
> + MT6360_PREFERCH_MASK, 0xF << MT6360_PREFERCH_SHFT);
> +out_adc:
> + mutex_unlock(&mad->adc_lock);
> +
> + return ret;
> +}
> +
> +static int mt6360_adc_read_raw(struct iio_dev *iio_dev,
> + const struct iio_chan_spec *chan,
> + int *val, int *val2, long mask)
> +{
> + struct mt6360_adc_data *mad = iio_priv(iio_dev);
> +
> + if (mask == IIO_CHAN_INFO_PROCESSED)
> + return mt6360_adc_read_processed(mad, chan->channel, val);
> +
> + return -EINVAL;
> +}
> +
> +static const struct iio_info mt6360_adc_iio_info = {
> + .read_raw = mt6360_adc_read_raw,
> +};
> +
> +#define MT6360_ADC_CHAN(_idx, _type) { \
> + .type = _type, \
> + .channel = MT6360_CHAN_##_idx, \
> + .scan_index = MT6360_CHAN_##_idx, \
> + .scan_type = { \
> + .sign = 's', \
> + .realbits = 32, \
> + .storagebits = 32, \
> + .shift = 0, \
shift = 0 is an obvious default so no need to specify it.
> + .endianness = IIO_CPU, \
> + }, \
> + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
> + .extend_name = #_idx, \
Extend name means you are defining new userspace ABI, so that
needs to be documented so we can discuss the necessity of doing so.
Documentation/ABI/testing/sysfs-bus-iio-*
> + .datasheet_name = #_idx, \
> + .indexed = 1, \
> +}
> +
> +static const struct iio_chan_spec mt6360_adc_channels[] = {
> + MT6360_ADC_CHAN(USBID, IIO_VOLTAGE),
> + MT6360_ADC_CHAN(VBUSDIV5, IIO_VOLTAGE),
> + MT6360_ADC_CHAN(VBUSDIV2, IIO_VOLTAGE),
> + MT6360_ADC_CHAN(VSYS, IIO_VOLTAGE),
> + MT6360_ADC_CHAN(VBAT, IIO_VOLTAGE),
> + MT6360_ADC_CHAN(IBUS, IIO_CURRENT),
> + MT6360_ADC_CHAN(IBAT, IIO_CURRENT),
> + MT6360_ADC_CHAN(CHG_VDDP, IIO_VOLTAGE),
> + MT6360_ADC_CHAN(TEMP_JC, IIO_TEMP),
> + MT6360_ADC_CHAN(VREF_TS, IIO_VOLTAGE),
> + MT6360_ADC_CHAN(TS, IIO_VOLTAGE),
> + IIO_CHAN_SOFT_TIMESTAMP(MT6360_CHAN_MAX),
> +};
> +
> +static irqreturn_t mt6360_pmu_adc_donei_handler(int irq, void *data)
> +{
> + struct mt6360_adc_data *mad = iio_priv(data);
> +
> + complete(&mad->adc_complete);
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t mt6360_adc_trigger_handler(int irq, void *p)
> +{
> + struct iio_poll_func *pf = p;
> + struct iio_dev *indio_dev = pf->indio_dev;
> + /* 11 ch s32 numbers + 1 s64 timestamp */
> + s32 data[MT6360_CHAN_MAX + 2] = { };
IIO requires that the timestamp that may be inserted in here
by iio_push_to_buffers_with_timestamp is 64 bit aligned.
In theory this array can be only 32 bit aligned. Hence tell
the compiler about this requirement with __aligned(8).
Note we are slowly working our way through fixing various historical
drivers that fell into this hole so you will currently find drivers
with this same problem in tree.
> + int i = 0, bit, val, ret;
> +
> + for_each_set_bit(bit,
> + indio_dev->active_scan_mask, indio_dev->masklength) {
Given the new relaxed view on the line length as long as it's below 100 and
helps readability, put the above on one line.
> + const struct iio_chan_spec *chan = indio_dev->channels + bit;
> +
> + ret = mt6360_adc_read_raw(indio_dev, chan, &val,
> + NULL, IIO_CHAN_INFO_PROCESSED);
> + if (ret != IIO_VAL_INT) {
> + dev_warn(&indio_dev->dev,
> + "Failed to get %d conversion val\n", bit);
> + goto out;
> + }
> +
> + data[i++] = val;
> + }
> + iio_push_to_buffers_with_timestamp(indio_dev,
> + data, iio_get_time_ns(indio_dev));
> +out:
> + iio_trigger_notify_done(indio_dev->trig);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static inline int mt6360_adc_reset(struct mt6360_adc_data *info)
> +{
> + u8 configs[3] = {0x80, 0, 0};
> + ktime_t all_off_time;
> + int i;
> +
> + all_off_time = ktime_get();
> + for (i = 0; i < MT6360_CHAN_MAX; i++)
> + info->last_off_timestamps[i] = all_off_time;
> +
> + /* enable adc_en, clear adc_chn_en/zcv_en/adc_wait_t/adc_idle_t */
> + return regmap_raw_write(info->regmap,
> + MT6360_REG_PMUADCCFG, configs, sizeof(configs));
> +}
> +
> +static int mt6360_adc_probe(struct platform_device *pdev)
> +{
> + struct mt6360_adc_data *mad;
> + struct iio_dev *indio_dev;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*mad));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + mad = iio_priv(indio_dev);
> + mad->dev = &pdev->dev;
> + init_completion(&mad->adc_complete);
> + mutex_init(&mad->adc_lock);
> +
> + mad->regmap = dev_get_regmap(pdev->dev.parent, NULL);
> + if (!mad->regmap) {
> + dev_err(&pdev->dev, "Failed to get parent regmap\n");
> + return -ENODEV;
> + }
> +
> + ret = mt6360_adc_reset(mad);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "Failed to reset adc\n");
> + return ret;
> + }
> +
> + mad->irq = platform_get_irq_byname(pdev, "adc_donei");
> + if (mad->irq < 0) {
> + dev_err(&pdev->dev, "Failed to get adc_done irq\n");
> + return mad->irq;
> + }
> +
> + irq_set_status_flags(mad->irq, IRQ_NOAUTOEN);
> + ret = devm_request_threaded_irq(&pdev->dev, mad->irq, NULL,
> + mt6360_pmu_adc_donei_handler,
> + IRQF_TRIGGER_NONE, "adc_donei",
> + indio_dev);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to register adc_done irq\n");
> + return ret;
> + }
> +
> + indio_dev->name = dev_name(&pdev->dev);
> + indio_dev->dev.parent = &pdev->dev;
> + indio_dev->info = &mt6360_adc_iio_info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = mt6360_adc_channels;
> + indio_dev->num_channels = ARRAY_SIZE(mt6360_adc_channels);
> +
> + ret = devm_iio_triggered_buffer_setup(&pdev->dev, indio_dev, NULL,
> + mt6360_adc_trigger_handler, NULL);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to allocate iio trigger buffer\n");
> + return ret;
> + }
> +
> + ret = devm_iio_device_register(&pdev->dev, indio_dev);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to register iio device\n");
> + return ret;
> + }
> +
> + platform_set_drvdata(pdev, indio_dev);
I can't immediately see where we use it?
> +
> + return 0;
> +}
> +
> +static const struct of_device_id __maybe_unused mt6360_adc_of_id[] = {
> + { .compatible = "mediatek,mt6360-adc", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, mt6360_adc_of_id);
> +
> +static struct platform_driver mt6360_adc_driver = {
> + .driver = {
> + .name = "mt6360-adc",
> + .of_match_table = mt6360_adc_of_id,
> + },
> + .probe = mt6360_adc_probe,
> +};
> +module_platform_driver(mt6360_adc_driver);
> +
> +MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>");
> +MODULE_DESCRIPTION("MT6360 ADC Driver");
> +MODULE_LICENSE("GPL v2");
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/4] mfd: mt6360: implement i2c R/W with CRC
2020-06-19 11:53 ` [PATCH v2 2/4] mfd: mt6360: implement i2c R/W with CRC Gene Chen
@ 2020-07-01 7:16 ` Lee Jones
2020-07-02 8:29 ` Gene Chen
0 siblings, 1 reply; 10+ messages in thread
From: Lee Jones @ 2020-07-01 7:16 UTC (permalink / raw)
To: Gene Chen
Cc: linux-arm-kernel, gene_chen, lars, pmeerw, lgirdwood,
linux-kernel, cy_huang, benjamin.chao, broonie, linux-mediatek,
jacek.anaszewski, pavel, knaack.h, matthias.bgg, shufan_lee,
jic23, dmurphy
On Fri, 19 Jun 2020, Gene Chen wrote:
> From: Gene Chen <gene_chen@richtek.com>
>
> imlement i2c R/W with CRC when access sub-device PMIC and LDO part
Please use proper grammar, including capital letters at the start of
the sentence and for abbreviations such as "I2C" and full stops.
Also this doesn't make sense to me. Please elaborate.
> Signed-off-by: Gene Chen <gene_chen@richtek.com>
> ---
> drivers/mfd/Kconfig | 1 +
> drivers/mfd/mt6360-core.c | 541 +++++++++++++++++++++++++++++----------------
This patch is doing way too much wacky stuff all at once, making it
very difficult to review. Please break it up into functional pieces
and submit as separate logical patches (in a set of course).
> include/linux/mfd/mt6360.h | 240 --------------------
> 3 files changed, 357 insertions(+), 425 deletions(-)
> delete mode 100644 include/linux/mfd/mt6360.h
--
Lee Jones [李琼斯]
Senior Technical Lead - Developer Services
Linaro.org │ Open source software for Arm SoCs
Follow Linaro: Facebook | Twitter | Blog
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/4] mfd: mt6360: implement i2c R/W with CRC
2020-07-01 7:16 ` Lee Jones
@ 2020-07-02 8:29 ` Gene Chen
2020-07-02 10:27 ` Lee Jones
0 siblings, 1 reply; 10+ messages in thread
From: Gene Chen @ 2020-07-02 8:29 UTC (permalink / raw)
To: Lee Jones
Cc: linux-arm-kernel, Gene Chen, lars, pmeerw, lgirdwood,
linux-kernel, cy_huang, benjamin.chao, Mark Brown,
linux-mediatek, jacek.anaszewski, pavel, knaack.h, matthias.bgg,
shufan_lee, jic23, dmurphy
Lee Jones <lee.jones@linaro.org> 於 2020年7月1日 週三 下午3:16寫道:
>
> On Fri, 19 Jun 2020, Gene Chen wrote:
>
> > From: Gene Chen <gene_chen@richtek.com>
> >
> > imlement i2c R/W with CRC when access sub-device PMIC and LDO part
>
> Please use proper grammar, including capital letters at the start of
> the sentence and for abbreviations such as "I2C" and full stops.
>
> Also this doesn't make sense to me. Please elaborate.
>
ACK
> > Signed-off-by: Gene Chen <gene_chen@richtek.com>
> > ---
> > drivers/mfd/Kconfig | 1 +
> > drivers/mfd/mt6360-core.c | 541 +++++++++++++++++++++++++++++----------------
>
> This patch is doing way too much wacky stuff all at once, making it
> very difficult to review. Please break it up into functional pieces
> and submit as separate logical patches (in a set of course).
>
If I understand correctly, I need to separate patch[2/4] but not
entire mt6362-core.c into several patches.
> > include/linux/mfd/mt6360.h | 240 --------------------
> > 3 files changed, 357 insertions(+), 425 deletions(-)
> > delete mode 100644 include/linux/mfd/mt6360.h
>
> --
> Lee Jones [李琼斯]
> Senior Technical Lead - Developer Services
> Linaro.org │ Open source software for Arm SoCs
> Follow Linaro: Facebook | Twitter | Blog
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/4] mfd: mt6360: implement i2c R/W with CRC
2020-07-02 8:29 ` Gene Chen
@ 2020-07-02 10:27 ` Lee Jones
0 siblings, 0 replies; 10+ messages in thread
From: Lee Jones @ 2020-07-02 10:27 UTC (permalink / raw)
To: Gene Chen
Cc: linux-arm-kernel, Gene Chen, lars, pmeerw, lgirdwood,
linux-kernel, cy_huang, benjamin.chao, Mark Brown,
linux-mediatek, jacek.anaszewski, pavel, knaack.h, matthias.bgg,
shufan_lee, jic23, dmurphy
On Thu, 02 Jul 2020, Gene Chen wrote:
> Lee Jones <lee.jones@linaro.org> 於 2020年7月1日 週三 下午3:16寫道:
> >
> > On Fri, 19 Jun 2020, Gene Chen wrote:
> >
> > > From: Gene Chen <gene_chen@richtek.com>
> > >
> > > imlement i2c R/W with CRC when access sub-device PMIC and LDO part
> >
> > Please use proper grammar, including capital letters at the start of
> > the sentence and for abbreviations such as "I2C" and full stops.
> >
> > Also this doesn't make sense to me. Please elaborate.
> >
>
> ACK
>
> > > Signed-off-by: Gene Chen <gene_chen@richtek.com>
> > > ---
> > > drivers/mfd/Kconfig | 1 +
> > > drivers/mfd/mt6360-core.c | 541 +++++++++++++++++++++++++++++----------------
> >
> > This patch is doing way too much wacky stuff all at once, making it
> > very difficult to review. Please break it up into functional pieces
> > and submit as separate logical patches (in a set of course).
> >
>
> If I understand correctly, I need to separate patch[2/4] but not
> entire mt6362-core.c into several patches.
Yes please.
--
Lee Jones [李琼斯]
Senior Technical Lead - Developer Services
Linaro.org │ Open source software for Arm SoCs
Follow Linaro: Facebook | Twitter | Blog
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2020-07-02 10:28 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-19 11:53 [PATCH v2 0/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 Gene Chen
2020-06-19 11:53 ` [PATCH v2 1/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 PMIC Gene Chen
2020-06-19 11:53 ` [PATCH v2 2/4] mfd: mt6360: implement i2c R/W with CRC Gene Chen
2020-07-01 7:16 ` Lee Jones
2020-07-02 8:29 ` Gene Chen
2020-07-02 10:27 ` Lee Jones
2020-06-19 11:53 ` [PATCH v2 3/4] iio: adc: mt6360: Add ADC driver for MT6360 Gene Chen
2020-06-20 17:03 ` Jonathan Cameron
2020-06-19 11:53 ` [PATCH v2 4/4] regulator: mt6360: Add support for MT6360 regulator Gene Chen
2020-06-20 16:55 ` [PATCH v2 0/4] dt-bindings: mfd: Add bindings for the Mediatek MT6360 Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).