55/*
66 * This version of the "BD86801 scalable PMIC"'s driver supports only very
77 * basic set of the PMIC features. Most notably, there is no support for
8- * the ERRB interrupt and the configurations which should be done when the
9- * PMIC is in STBY mode.
10- *
11- * Supporting the ERRB interrupt would require dropping the regmap-IRQ
12- * usage or working around (or accepting a presense of) a naming conflict
13- * in debugFS IRQs.
8+ * the configurations which should be done when the PMIC is in STBY mode.
149 *
1510 * Being able to reliably do the configurations like changing the
1611 * regulator safety limits (like limits for the over/under -voltages, over
2217 * be the need to configure these safety limits. Hence it's not simple to
2318 * come up with a generic solution.
2419 *
25- * Users who require the ERRB handling and STBY state configurations can
26- * have a look at the original RFC:
20+ * Users who require the STBY state configurations can have a look at the
21+ * original RFC:
2722 * https://lore.kernel.org/all/cover.1712920132.git.mazziesaccount@gmail.com/
28- * which implements a workaround to debugFS naming conflict and some of
29- * the safety limit configurations - but leaves the state change handling
30- * and synchronization to be implemented.
23+ * which implements some of the safety limit configurations - but leaves the
24+ * state change handling and synchronization to be implemented.
3125 *
3226 * It would be great to hear (and receive a patch!) if you implement the
33- * STBY configuration support or a proper fix to the debugFS naming
34- * conflict in your downstream driver ;)
27+ * STBY configuration support in your downstream driver ;)
3528 */
3629
3730#include <linux/cleanup.h>
@@ -728,6 +721,95 @@ static int initialize_pmic_data(struct device *dev,
728721 return 0 ;
729722}
730723
724+ static int bd96801_map_event_all (int irq , struct regulator_irq_data * rid ,
725+ unsigned long * dev_mask )
726+ {
727+ int i ;
728+
729+ for (i = 0 ; i < rid -> num_states ; i ++ ) {
730+ rid -> states [i ].notifs = REGULATOR_EVENT_FAIL ;
731+ rid -> states [i ].errors = REGULATOR_ERROR_FAIL ;
732+ * dev_mask |= BIT (i );
733+ }
734+
735+ return 0 ;
736+ }
737+
738+ static int bd96801_rdev_errb_irqs (struct platform_device * pdev ,
739+ struct regulator_dev * rdev )
740+ {
741+ int i ;
742+ void * retp ;
743+ static const char * const single_out_errb_irqs [] = {
744+ "bd96801-%s-pvin-err" , "bd96801-%s-ovp-err" ,
745+ "bd96801-%s-uvp-err" , "bd96801-%s-shdn-err" ,
746+ };
747+
748+ for (i = 0 ; i < ARRAY_SIZE (single_out_errb_irqs ); i ++ ) {
749+ struct regulator_irq_desc id = {
750+ .map_event = bd96801_map_event_all ,
751+ .irq_off_ms = 1000 ,
752+ };
753+ struct regulator_dev * rdev_arr [1 ];
754+ char tmp [255 ];
755+ int irq ;
756+
757+ snprintf (tmp , 255 , single_out_errb_irqs [i ], rdev -> desc -> name );
758+ tmp [254 ] = 0 ;
759+ id .name = tmp ;
760+
761+ irq = platform_get_irq_byname (pdev , tmp );
762+ if (irq < 0 )
763+ continue ;
764+
765+ rdev_arr [0 ] = rdev ;
766+ retp = devm_regulator_irq_helper (& pdev -> dev , & id , irq , 0 ,
767+ REGULATOR_ERROR_FAIL , NULL ,
768+ rdev_arr , 1 );
769+ if (IS_ERR (retp ))
770+ return PTR_ERR (retp );
771+
772+ }
773+ return 0 ;
774+ }
775+
776+ static int bd96801_global_errb_irqs (struct platform_device * pdev ,
777+ struct regulator_dev * * rdev , int num_rdev )
778+ {
779+ int i , num_irqs ;
780+ void * retp ;
781+ static const char * const global_errb_irqs [] = {
782+ "bd96801-otp-err" , "bd96801-dbist-err" , "bd96801-eep-err" ,
783+ "bd96801-abist-err" , "bd96801-prstb-err" , "bd96801-drmoserr1" ,
784+ "bd96801-drmoserr2" , "bd96801-slave-err" , "bd96801-vref-err" ,
785+ "bd96801-tsd" , "bd96801-uvlo-err" , "bd96801-ovlo-err" ,
786+ "bd96801-osc-err" , "bd96801-pon-err" , "bd96801-poff-err" ,
787+ "bd96801-cmd-shdn-err" , "bd96801-int-shdn-err"
788+ };
789+
790+ num_irqs = ARRAY_SIZE (global_errb_irqs );
791+ for (i = 0 ; i < num_irqs ; i ++ ) {
792+ int irq ;
793+ struct regulator_irq_desc id = {
794+ .name = global_errb_irqs [i ],
795+ .map_event = bd96801_map_event_all ,
796+ .irq_off_ms = 1000 ,
797+ };
798+
799+ irq = platform_get_irq_byname (pdev , global_errb_irqs [i ]);
800+ if (irq < 0 )
801+ continue ;
802+
803+ retp = devm_regulator_irq_helper (& pdev -> dev , & id , irq , 0 ,
804+ REGULATOR_ERROR_FAIL , NULL ,
805+ rdev , num_rdev );
806+ if (IS_ERR (retp ))
807+ return PTR_ERR (retp );
808+ }
809+
810+ return 0 ;
811+ }
812+
731813static int bd96801_rdev_intb_irqs (struct platform_device * pdev ,
732814 struct bd96801_pmic_data * pdata ,
733815 struct bd96801_irqinfo * iinfo ,
@@ -783,18 +865,18 @@ static int bd96801_rdev_intb_irqs(struct platform_device *pdev,
783865 return 0 ;
784866}
785867
786-
787-
788868static int bd96801_probe (struct platform_device * pdev )
789869{
790870 struct regulator_dev * ldo_errs_rdev_arr [BD96801_NUM_LDOS ];
871+ struct regulator_dev * all_rdevs [BD96801_NUM_REGULATORS ];
791872 struct bd96801_regulator_data * rdesc ;
792873 struct regulator_config config = {};
793874 int ldo_errs_arr [BD96801_NUM_LDOS ];
794875 struct bd96801_pmic_data * pdata ;
795876 int temp_notif_ldos = 0 ;
796877 struct device * parent ;
797878 int i , ret ;
879+ bool use_errb ;
798880 void * retp ;
799881
800882 parent = pdev -> dev .parent ;
@@ -819,6 +901,13 @@ static int bd96801_probe(struct platform_device *pdev)
819901 config .regmap = pdata -> regmap ;
820902 config .dev = parent ;
821903
904+ ret = of_property_match_string (pdev -> dev .parent -> of_node ,
905+ "interrupt-names" , "errb" );
906+ if (ret < 0 )
907+ use_errb = false;
908+ else
909+ use_errb = true;
910+
822911 ret = bd96801_walk_regulator_dt (& pdev -> dev , pdata -> regmap , rdesc ,
823912 BD96801_NUM_REGULATORS );
824913 if (ret )
@@ -837,6 +926,7 @@ static int bd96801_probe(struct platform_device *pdev)
837926 rdesc [i ].desc .name );
838927 return PTR_ERR (rdev );
839928 }
929+ all_rdevs [i ] = rdev ;
840930 /*
841931 * LDOs don't have own temperature monitoring. If temperature
842932 * notification was requested for this LDO from DT then we will
@@ -856,6 +946,12 @@ static int bd96801_probe(struct platform_device *pdev)
856946 if (ret )
857947 return ret ;
858948 }
949+ /* Register per regulator ERRB notifiers */
950+ if (use_errb ) {
951+ ret = bd96801_rdev_errb_irqs (pdev , rdev );
952+ if (ret )
953+ return ret ;
954+ }
859955 }
860956 if (temp_notif_ldos ) {
861957 int irq ;
@@ -877,6 +973,10 @@ static int bd96801_probe(struct platform_device *pdev)
877973 return PTR_ERR (retp );
878974 }
879975
976+ if (use_errb )
977+ return bd96801_global_errb_irqs (pdev , all_rdevs ,
978+ ARRAY_SIZE (all_rdevs ));
979+
880980 return 0 ;
881981}
882982
0 commit comments