|
@@ -31,11 +31,17 @@
|
|
|
|
|
|
#define PFUZE100_COINVOL 0x1a
|
|
|
#define PFUZE100_SW1ABVOL 0x20
|
|
|
+#define PFUZE100_SW1ABMODE 0x23
|
|
|
#define PFUZE100_SW1CVOL 0x2e
|
|
|
+#define PFUZE100_SW1CMODE 0x31
|
|
|
#define PFUZE100_SW2VOL 0x35
|
|
|
+#define PFUZE100_SW2MODE 0x38
|
|
|
#define PFUZE100_SW3AVOL 0x3c
|
|
|
+#define PFUZE100_SW3AMODE 0x3f
|
|
|
#define PFUZE100_SW3BVOL 0x43
|
|
|
+#define PFUZE100_SW3BMODE 0x46
|
|
|
#define PFUZE100_SW4VOL 0x4a
|
|
|
+#define PFUZE100_SW4MODE 0x4d
|
|
|
#define PFUZE100_SWBSTCON1 0x66
|
|
|
#define PFUZE100_VREFDDRCON 0x6a
|
|
|
#define PFUZE100_VSNVSVOL 0x6b
|
|
@@ -46,6 +52,13 @@
|
|
|
#define PFUZE100_VGEN5VOL 0x70
|
|
|
#define PFUZE100_VGEN6VOL 0x71
|
|
|
|
|
|
+#define PFUZE100_SWxMODE_MASK 0xf
|
|
|
+#define PFUZE100_SWxMODE_APS_APS 0x8
|
|
|
+#define PFUZE100_SWxMODE_APS_OFF 0x4
|
|
|
+
|
|
|
+#define PFUZE100_VGENxLPWR BIT(6)
|
|
|
+#define PFUZE100_VGENxSTBY BIT(5)
|
|
|
+
|
|
|
enum chips { PFUZE100, PFUZE200, PFUZE3000 = 3, PFUZE3001 = 0x31, };
|
|
|
|
|
|
struct pfuze_regulator {
|
|
@@ -559,6 +572,69 @@ static inline struct device_node *match_of_node(int index)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+static struct pfuze_chip *syspm_pfuze_chip;
|
|
|
+
|
|
|
+static void pfuze_power_off_prepare(void)
|
|
|
+{
|
|
|
+ dev_info(syspm_pfuze_chip->dev, "Configure standby mode for power off");
|
|
|
+
|
|
|
+ /* Switch from default mode: APS/APS to APS/Off */
|
|
|
+ regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_SW1ABMODE,
|
|
|
+ PFUZE100_SWxMODE_MASK, PFUZE100_SWxMODE_APS_OFF);
|
|
|
+ regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_SW1CMODE,
|
|
|
+ PFUZE100_SWxMODE_MASK, PFUZE100_SWxMODE_APS_OFF);
|
|
|
+ regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_SW2MODE,
|
|
|
+ PFUZE100_SWxMODE_MASK, PFUZE100_SWxMODE_APS_OFF);
|
|
|
+ regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_SW3AMODE,
|
|
|
+ PFUZE100_SWxMODE_MASK, PFUZE100_SWxMODE_APS_OFF);
|
|
|
+ regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_SW3BMODE,
|
|
|
+ PFUZE100_SWxMODE_MASK, PFUZE100_SWxMODE_APS_OFF);
|
|
|
+ regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_SW4MODE,
|
|
|
+ PFUZE100_SWxMODE_MASK, PFUZE100_SWxMODE_APS_OFF);
|
|
|
+
|
|
|
+ regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_VGEN1VOL,
|
|
|
+ PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY,
|
|
|
+ PFUZE100_VGENxSTBY);
|
|
|
+ regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_VGEN2VOL,
|
|
|
+ PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY,
|
|
|
+ PFUZE100_VGENxSTBY);
|
|
|
+ regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_VGEN3VOL,
|
|
|
+ PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY,
|
|
|
+ PFUZE100_VGENxSTBY);
|
|
|
+ regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_VGEN4VOL,
|
|
|
+ PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY,
|
|
|
+ PFUZE100_VGENxSTBY);
|
|
|
+ regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_VGEN5VOL,
|
|
|
+ PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY,
|
|
|
+ PFUZE100_VGENxSTBY);
|
|
|
+ regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_VGEN6VOL,
|
|
|
+ PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY,
|
|
|
+ PFUZE100_VGENxSTBY);
|
|
|
+}
|
|
|
+
|
|
|
+static int pfuze_power_off_prepare_init(struct pfuze_chip *pfuze_chip)
|
|
|
+{
|
|
|
+ if (pfuze_chip->chip_id != PFUZE100) {
|
|
|
+ dev_warn(pfuze_chip->dev, "Requested pm_power_off_prepare handler for not supported chip\n");
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pm_power_off_prepare) {
|
|
|
+ dev_warn(pfuze_chip->dev, "pm_power_off_prepare is already registered.\n");
|
|
|
+ return -EBUSY;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (syspm_pfuze_chip) {
|
|
|
+ dev_warn(pfuze_chip->dev, "syspm_pfuze_chip is already set.\n");
|
|
|
+ return -EBUSY;
|
|
|
+ }
|
|
|
+
|
|
|
+ syspm_pfuze_chip = pfuze_chip;
|
|
|
+ pm_power_off_prepare = pfuze_power_off_prepare;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int pfuze_identify(struct pfuze_chip *pfuze_chip)
|
|
|
{
|
|
|
unsigned int value;
|
|
@@ -753,6 +829,20 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (of_property_read_bool(client->dev.of_node,
|
|
|
+ "fsl,pmic-stby-poweroff"))
|
|
|
+ return pfuze_power_off_prepare_init(pfuze_chip);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int pfuze100_regulator_remove(struct i2c_client *client)
|
|
|
+{
|
|
|
+ if (syspm_pfuze_chip) {
|
|
|
+ syspm_pfuze_chip = NULL;
|
|
|
+ pm_power_off_prepare = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -763,6 +853,7 @@ static struct i2c_driver pfuze_driver = {
|
|
|
.of_match_table = pfuze_dt_ids,
|
|
|
},
|
|
|
.probe = pfuze100_regulator_probe,
|
|
|
+ .remove = pfuze100_regulator_remove,
|
|
|
};
|
|
|
module_i2c_driver(pfuze_driver);
|
|
|
|