aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Baryshkov <dmitry.baryshkov@linaro.org>2020-10-22 01:34:40 +0300
committerDmitry Baryshkov <dmitry.baryshkov@linaro.org>2020-10-30 04:01:12 +0300
commit4d1820c617bd8c0f717d4dd9d9b297e8e620042d (patch)
treebd7696b60e7db3f1f1cfd4b351a1ab1c4458537d
parent67f0b0ffcb8472fe9f0a699d35a74b81d31715c5 (diff)
leds: qcom-lpg: add support for pm8150[bl] leds
Add support for the LPG/PWM block found on newer PMICs: PM8150B and PM8150A/L. Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
-rw-r--r--drivers/leds/leds-qcom-lpg.c68
1 files changed, 61 insertions, 7 deletions
diff --git a/drivers/leds/leds-qcom-lpg.c b/drivers/leds/leds-qcom-lpg.c
index 86131a65d2c5..4770fc46f312 100644
--- a/drivers/leds/leds-qcom-lpg.c
+++ b/drivers/leds/leds-qcom-lpg.c
@@ -48,6 +48,8 @@ struct lpg_data;
* @lut_bitmap: allocation bitmap for LUT entries
* @triled_base: base address of the TRILED block (optional)
* @triled_src: power-source for the TRILED
+ * @triled_has_atc_ctl: true if there is TRI_LED_ATC_CTL register
+ * @triled_has_src_sel: true if there is TRI_LED_SRC_SEL register
* @channels: list of PWM channels
* @num_channels: number of @channels
*/
@@ -65,6 +67,8 @@ struct lpg {
u32 triled_base;
u32 triled_src;
+ bool triled_has_atc_ctl;
+ bool triled_has_src_sel;
struct lpg_channel *channels;
unsigned int num_channels;
@@ -165,6 +169,8 @@ struct lpg_channel_data {
* @lut_base: base address of LUT block
* @lut_size: number of entries in LUT
* @triled_base: base address of TRILED
+ * @triled_has_atc_ctl: true if there is TRI_LED_ATC_CTL register
+ * @triled_has_src_sel: true if there is TRI_LED_SRC_SEL register
* @pwm_9bit_mask: bitmask for switching from 6bit to 9bit pwm
* @num_channels: number of channels in LPG
* @channels: list of channel initialization data
@@ -173,6 +179,8 @@ struct lpg_data {
unsigned int lut_base;
unsigned int lut_size;
unsigned int triled_base;
+ bool triled_has_atc_ctl;
+ bool triled_has_src_sel;
unsigned int pwm_9bit_mask;
int num_channels;
struct lpg_channel_data *channels;
@@ -986,18 +994,24 @@ static int lpg_init_triled(struct lpg *lpg)
return 0;
lpg->triled_base = lpg->data->triled_base;
-
- ret = of_property_read_u32(np, "qcom,power-source", &lpg->triled_src);
- if (ret || lpg->triled_src == 2 || lpg->triled_src > 3) {
- dev_err(lpg->dev, "invalid power source\n");
- return -EINVAL;
+ lpg->triled_has_atc_ctl = lpg->data->triled_has_atc_ctl;
+ lpg->triled_has_src_sel = lpg->data->triled_has_src_sel;
+
+ if (lpg->triled_has_src_sel) {
+ ret = of_property_read_u32(np, "qcom,power-source", &lpg->triled_src);
+ if (ret || lpg->triled_src == 2 || lpg->triled_src > 3) {
+ dev_err(lpg->dev, "invalid power source\n");
+ return -EINVAL;
+ }
}
/* Disable automatic trickle charge LED */
- regmap_write(lpg->map, lpg->triled_base + TRI_LED_ATC_CTL, 0);
+ if (lpg->triled_has_atc_ctl)
+ regmap_write(lpg->map, lpg->triled_base + TRI_LED_ATC_CTL, 0);
/* Configure power source */
- regmap_write(lpg->map, lpg->triled_base + TRI_LED_SRC_SEL, lpg->triled_src);
+ if (lpg->triled_has_src_sel)
+ regmap_write(lpg->map, lpg->triled_base + TRI_LED_SRC_SEL, lpg->triled_src);
/* Default all outputs to off */
regmap_write(lpg->map, lpg->triled_base + TRI_LED_EN_CTL, 0);
@@ -1099,6 +1113,8 @@ static const struct lpg_data pm8941_lpg_data = {
.lut_size = 64,
.triled_base = 0xd000,
+ .triled_has_atc_ctl = true,
+ .triled_has_src_sel = true,
.pwm_9bit_mask = 3 << 4,
@@ -1137,6 +1153,8 @@ static const struct lpg_data pmi8994_lpg_data = {
.lut_size = 24,
.triled_base = 0xd000,
+ .triled_has_atc_ctl = true,
+ .triled_has_src_sel = true,
.pwm_9bit_mask = BIT(4),
@@ -1166,12 +1184,48 @@ static const struct lpg_data pmi8998_lpg_data = {
},
};
+static const struct lpg_data pm8150b_lpg_data = {
+ .lut_base = 0xb000,
+ .lut_size = 49,
+
+ .triled_base = 0xd000,
+
+ .pwm_9bit_mask = BIT(4),
+
+ .num_channels = 2,
+ .channels = (struct lpg_channel_data[]) {
+ { .base = 0xb100, .triled_mask = BIT(7) },
+ { .base = 0xb200, .triled_mask = BIT(6) },
+ },
+};
+
+static const struct lpg_data pm8150l_lpg_data = {
+ .lut_base = 0xb000,
+ .lut_size = 49,
+
+ .triled_base = 0xd000,
+
+ .pwm_9bit_mask = BIT(4),
+
+ .num_channels = 5,
+ .channels = (struct lpg_channel_data[]) {
+ { .base = 0xb100, .triled_mask = BIT(7) },
+ { .base = 0xb200, .triled_mask = BIT(6) },
+ { .base = 0xb300, .triled_mask = BIT(5) },
+ { .base = 0xbc00 },
+ { .base = 0xbd00 },
+
+ },
+};
+
static const struct of_device_id lpg_of_table[] = {
{ .compatible = "qcom,pm8916-pwm", .data = &pm8916_pwm_data },
{ .compatible = "qcom,pm8941-lpg", .data = &pm8941_lpg_data },
{ .compatible = "qcom,pm8994-lpg", .data = &pm8994_lpg_data },
{ .compatible = "qcom,pmi8994-lpg", .data = &pmi8994_lpg_data },
{ .compatible = "qcom,pmi8998-lpg", .data = &pmi8998_lpg_data },
+ { .compatible = "qcom,pm8150b-lpg", .data = &pm8150b_lpg_data },
+ { .compatible = "qcom,pm8150l-lpg", .data = &pm8150l_lpg_data },
{}
};
MODULE_DEVICE_TABLE(of, lpg_of_table);