Skip to content

Commit 2a7e727

Browse files
baolin-wangLee Jones
authored andcommitted
mfd: sc27xx: Add USB charger type detection support
The Spreadtrum SC27XX series PMICs supply the USB charger type detection function, and related registers are located on the PMIC global registers region, thus we implement and export this function in the MFD driver for users to get the USB charger type. Signed-off-by: Baolin Wang <[email protected]> Signed-off-by: Lee Jones <[email protected]>
1 parent ba58369 commit 2a7e727

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

drivers/mfd/sprd-sc27xx-spi.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,39 @@
1010
#include <linux/of_device.h>
1111
#include <linux/regmap.h>
1212
#include <linux/spi/spi.h>
13+
#include <uapi/linux/usb/charger.h>
1314

1415
#define SPRD_PMIC_INT_MASK_STATUS 0x0
1516
#define SPRD_PMIC_INT_RAW_STATUS 0x4
1617
#define SPRD_PMIC_INT_EN 0x8
1718

1819
#define SPRD_SC2731_IRQ_BASE 0x140
1920
#define SPRD_SC2731_IRQ_NUMS 16
21+
#define SPRD_SC2731_CHG_DET 0xedc
22+
23+
/* PMIC charger detection definition */
24+
#define SPRD_PMIC_CHG_DET_DELAY_US 200000
25+
#define SPRD_PMIC_CHG_DET_TIMEOUT 2000000
26+
#define SPRD_PMIC_CHG_DET_DONE BIT(11)
27+
#define SPRD_PMIC_SDP_TYPE BIT(7)
28+
#define SPRD_PMIC_DCP_TYPE BIT(6)
29+
#define SPRD_PMIC_CDP_TYPE BIT(5)
30+
#define SPRD_PMIC_CHG_TYPE_MASK GENMASK(7, 5)
2031

2132
struct sprd_pmic {
2233
struct regmap *regmap;
2334
struct device *dev;
2435
struct regmap_irq *irqs;
2536
struct regmap_irq_chip irq_chip;
2637
struct regmap_irq_chip_data *irq_data;
38+
const struct sprd_pmic_data *pdata;
2739
int irq;
2840
};
2941

3042
struct sprd_pmic_data {
3143
u32 irq_base;
3244
u32 num_irqs;
45+
u32 charger_det;
3346
};
3447

3548
/*
@@ -40,8 +53,46 @@ struct sprd_pmic_data {
4053
static const struct sprd_pmic_data sc2731_data = {
4154
.irq_base = SPRD_SC2731_IRQ_BASE,
4255
.num_irqs = SPRD_SC2731_IRQ_NUMS,
56+
.charger_det = SPRD_SC2731_CHG_DET,
4357
};
4458

59+
enum usb_charger_type sprd_pmic_detect_charger_type(struct device *dev)
60+
{
61+
struct spi_device *spi = to_spi_device(dev);
62+
struct sprd_pmic *ddata = spi_get_drvdata(spi);
63+
const struct sprd_pmic_data *pdata = ddata->pdata;
64+
enum usb_charger_type type;
65+
u32 val;
66+
int ret;
67+
68+
ret = regmap_read_poll_timeout(ddata->regmap, pdata->charger_det, val,
69+
(val & SPRD_PMIC_CHG_DET_DONE),
70+
SPRD_PMIC_CHG_DET_DELAY_US,
71+
SPRD_PMIC_CHG_DET_TIMEOUT);
72+
if (ret) {
73+
dev_err(&spi->dev, "failed to detect charger type\n");
74+
return UNKNOWN_TYPE;
75+
}
76+
77+
switch (val & SPRD_PMIC_CHG_TYPE_MASK) {
78+
case SPRD_PMIC_CDP_TYPE:
79+
type = CDP_TYPE;
80+
break;
81+
case SPRD_PMIC_DCP_TYPE:
82+
type = DCP_TYPE;
83+
break;
84+
case SPRD_PMIC_SDP_TYPE:
85+
type = SDP_TYPE;
86+
break;
87+
default:
88+
type = UNKNOWN_TYPE;
89+
break;
90+
}
91+
92+
return type;
93+
}
94+
EXPORT_SYMBOL_GPL(sprd_pmic_detect_charger_type);
95+
4596
static const struct mfd_cell sprd_pmic_devs[] = {
4697
{
4798
.name = "sc27xx-wdt",
@@ -181,6 +232,7 @@ static int sprd_pmic_probe(struct spi_device *spi)
181232
spi_set_drvdata(spi, ddata);
182233
ddata->dev = &spi->dev;
183234
ddata->irq = spi->irq;
235+
ddata->pdata = pdata;
184236

185237
ddata->irq_chip.name = dev_name(&spi->dev);
186238
ddata->irq_chip.status_base =

include/linux/mfd/sc27xx-pmic.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef __LINUX_MFD_SC27XX_PMIC_H
3+
#define __LINUX_MFD_SC27XX_PMIC_H
4+
5+
extern enum usb_charger_type sprd_pmic_detect_charger_type(struct device *dev);
6+
7+
#endif /* __LINUX_MFD_SC27XX_PMIC_H */

0 commit comments

Comments
 (0)