[PATCH v2 3/5] mfd: sprd-sc27xx: Switch to devm_mfd_add_devices()

Otto Pflüger posted 5 patches 1 week, 1 day ago
There is a newer version of this series
[PATCH v2 3/5] mfd: sprd-sc27xx: Switch to devm_mfd_add_devices()
Posted by Otto Pflüger 1 week, 1 day ago
To allow instantiating subdevices such as the regulator and poweroff
devices that do not have corresponding device tree nodes with a
"compatible" property, use devm_mfd_add_devices() with MFD cells instead
of devm_of_platform_populate(). Since different PMICs in the SC27xx
series contain different components, use separate MFD cell tables for
each PMIC model. Define cells for all components that have upstream
drivers at this point.

Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
 drivers/mfd/sprd-sc27xx-spi.c | 62 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 53 insertions(+), 9 deletions(-)

diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c
index d6b4350779e6..eb57023fdc3c 100644
--- a/drivers/mfd/sprd-sc27xx-spi.c
+++ b/drivers/mfd/sprd-sc27xx-spi.c
@@ -14,6 +14,11 @@
 #include <linux/spi/spi.h>
 #include <uapi/linux/usb/charger.h>
 
+enum sprd_pmic_type {
+	PMIC_TYPE_SC2730,
+	PMIC_TYPE_SC2731,
+};
+
 #define SPRD_PMIC_INT_MASK_STATUS	0x0
 #define SPRD_PMIC_INT_RAW_STATUS	0x4
 #define SPRD_PMIC_INT_EN		0x8
@@ -50,6 +55,29 @@ struct sprd_pmic_data {
 	u32 charger_det;
 };
 
+static const struct mfd_cell sc2730_devices[] = {
+	MFD_CELL_OF("sc2730-adc", NULL, NULL, 0, 0, "sprd,sc2730-adc"),
+	MFD_CELL_OF("sc2730-bltc", NULL, NULL, 0, 0, "sprd,sc2730-bltc"),
+	MFD_CELL_OF("sc2730-efuse", NULL, NULL, 0, 0, "sprd,sc2730-efuse"),
+	MFD_CELL_OF("sc2730-eic", NULL, NULL, 0, 0, "sprd,sc2730-eic"),
+	MFD_CELL_OF("sc2730-fgu", NULL, NULL, 0, 0, "sprd,sc2730-fgu"),
+	MFD_CELL_OF("sc2730-rtc", NULL, NULL, 0, 0, "sprd,sc2730-rtc"),
+	MFD_CELL_OF("sc2730-vibrator", NULL, NULL, 0, 0, "sprd,sc2730-vibrator"),
+};
+
+static const struct mfd_cell sc2731_devices[] = {
+	MFD_CELL_OF("sc2731-adc", NULL, NULL, 0, 0, "sprd,sc2731-adc"),
+	MFD_CELL_OF("sc2731-bltc", NULL, NULL, 0, 0, "sprd,sc2731-bltc"),
+	MFD_CELL_OF("sc2731-charger", NULL, NULL, 0, 0, "sprd,sc2731-charger"),
+	MFD_CELL_OF("sc2731-efuse", NULL, NULL, 0, 0, "sprd,sc2731-efuse"),
+	MFD_CELL_OF("sc2731-eic", NULL, NULL, 0, 0, "sprd,sc2731-eic"),
+	MFD_CELL_OF("sc2731-fgu", NULL, NULL, 0, 0, "sprd,sc2731-fgu"),
+	MFD_CELL_NAME("sc2731-poweroff"),
+	MFD_CELL_NAME("sc2731-regulator"),
+	MFD_CELL_OF("sc2731-rtc", NULL, NULL, 0, 0, "sprd,sc2731-rtc"),
+	MFD_CELL_OF("sc2731-vibrator", NULL, NULL, 0, 0, "sprd,sc2731-vibrator"),
+};
+
 /*
  * Since different PMICs of SC27xx series can have different interrupt
  * base address and irq number, we should save irq number and irq base
@@ -152,12 +180,26 @@ static const struct regmap_config sprd_pmic_config = {
 static int sprd_pmic_probe(struct spi_device *spi)
 {
 	struct sprd_pmic *ddata;
+	enum sprd_pmic_type pmic_type;
 	const struct sprd_pmic_data *pdata;
-	int ret, i;
+	const struct mfd_cell *cells;
+	int ret, i, num_cells;
+
+	pmic_type = (enum sprd_pmic_type)of_device_get_match_data(&spi->dev);
 
-	pdata = of_device_get_match_data(&spi->dev);
-	if (!pdata) {
-		dev_err(&spi->dev, "No matching driver data found\n");
+	switch (pmic_type) {
+	case PMIC_TYPE_SC2730:
+		pdata = &sc2730_data;
+		cells = sc2730_devices;
+		num_cells = ARRAY_SIZE(sc2730_devices);
+		break;
+	case PMIC_TYPE_SC2731:
+		pdata = &sc2731_data;
+		cells = sc2731_devices;
+		num_cells = ARRAY_SIZE(sc2731_devices);
+		break;
+	default:
+		dev_err(&spi->dev, "Invalid device ID\n");
 		return -EINVAL;
 	}
 
@@ -204,7 +246,9 @@ static int sprd_pmic_probe(struct spi_device *spi)
 		return ret;
 	}
 
-	ret = devm_of_platform_populate(&spi->dev);
+	ret = devm_mfd_add_devices(&spi->dev, PLATFORM_DEVID_AUTO,
+				   cells, num_cells, NULL, 0,
+				   regmap_irq_get_domain(ddata->irq_data));
 	if (ret) {
 		dev_err(&spi->dev, "Failed to populate sub-devices %d\n", ret);
 		return ret;
@@ -241,15 +285,15 @@ static DEFINE_SIMPLE_DEV_PM_OPS(sprd_pmic_pm_ops,
 				sprd_pmic_suspend, sprd_pmic_resume);
 
 static const struct of_device_id sprd_pmic_match[] = {
-	{ .compatible = "sprd,sc2730", .data = &sc2730_data },
-	{ .compatible = "sprd,sc2731", .data = &sc2731_data },
+	{ .compatible = "sprd,sc2730", .data = (void *)PMIC_TYPE_SC2730 },
+	{ .compatible = "sprd,sc2731", .data = (void *)PMIC_TYPE_SC2731 },
 	{},
 };
 MODULE_DEVICE_TABLE(of, sprd_pmic_match);
 
 static const struct spi_device_id sprd_pmic_spi_ids[] = {
-	{ .name = "sc2730", .driver_data = (unsigned long)&sc2730_data },
-	{ .name = "sc2731", .driver_data = (unsigned long)&sc2731_data },
+	{ .name = "sc2730", .driver_data = PMIC_TYPE_SC2730 },
+	{ .name = "sc2731", .driver_data = PMIC_TYPE_SC2731 },
 	{},
 };
 MODULE_DEVICE_TABLE(spi, sprd_pmic_spi_ids);

-- 
2.51.0

Re: [PATCH v2 3/5] mfd: sprd-sc27xx: Switch to devm_mfd_add_devices()
Posted by kernel test robot 4 days, 22 hours ago
Hi Otto,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 85964cdcad0fac9a0eb7b87a0f9d88cc074b854c]

url:    https://github.com/intel-lab-lkp/linux/commits/Otto-Pfl-ger/dt-bindings-rtc-sc2731-Add-compatible-for-SC2730/20260327-162827
base:   85964cdcad0fac9a0eb7b87a0f9d88cc074b854c
patch link:    https://lore.kernel.org/r/20260325-sc27xx-mfd-cells-v2-3-d0ebb60aa4a7%40abscue.de
patch subject: [PATCH v2 3/5] mfd: sprd-sc27xx: Switch to devm_mfd_add_devices()
config: sparc64-allmodconfig (https://download.01.org/0day-ci/archive/20260329/202603291013.6DnmGjG3-lkp@intel.com/config)
compiler: clang version 23.0.0git (https://github.com/llvm/llvm-project 054e11d1a17e5ba88bb1a8ef32fad3346e80b186)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260329/202603291013.6DnmGjG3-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603291013.6DnmGjG3-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/mfd/sprd-sc27xx-spi.c:188:14: warning: cast to smaller integer type 'enum sprd_pmic_type' from 'const void *' [-Wvoid-pointer-to-enum-cast]
     188 |         pmic_type = (enum sprd_pmic_type)of_device_get_match_data(&spi->dev);
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1 warning generated.


vim +188 drivers/mfd/sprd-sc27xx-spi.c

   179	
   180	static int sprd_pmic_probe(struct spi_device *spi)
   181	{
   182		struct sprd_pmic *ddata;
   183		enum sprd_pmic_type pmic_type;
   184		const struct sprd_pmic_data *pdata;
   185		const struct mfd_cell *cells;
   186		int ret, i, num_cells;
   187	
 > 188		pmic_type = (enum sprd_pmic_type)of_device_get_match_data(&spi->dev);
   189	
   190		switch (pmic_type) {
   191		case PMIC_TYPE_SC2730:
   192			pdata = &sc2730_data;
   193			cells = sc2730_devices;
   194			num_cells = ARRAY_SIZE(sc2730_devices);
   195			break;
   196		case PMIC_TYPE_SC2731:
   197			pdata = &sc2731_data;
   198			cells = sc2731_devices;
   199			num_cells = ARRAY_SIZE(sc2731_devices);
   200			break;
   201		default:
   202			dev_err(&spi->dev, "Invalid device ID\n");
   203			return -EINVAL;
   204		}
   205	
   206		ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
   207		if (!ddata)
   208			return -ENOMEM;
   209	
   210		ddata->regmap = devm_regmap_init(&spi->dev, &sprd_pmic_regmap,
   211						 &spi->dev, &sprd_pmic_config);
   212		if (IS_ERR(ddata->regmap)) {
   213			ret = PTR_ERR(ddata->regmap);
   214			dev_err(&spi->dev, "Failed to allocate register map %d\n", ret);
   215			return ret;
   216		}
   217	
   218		spi_set_drvdata(spi, ddata);
   219		ddata->dev = &spi->dev;
   220		ddata->irq = spi->irq;
   221		ddata->pdata = pdata;
   222	
   223		ddata->irq_chip.name = dev_name(&spi->dev);
   224		ddata->irq_chip.status_base =
   225			pdata->irq_base + SPRD_PMIC_INT_MASK_STATUS;
   226		ddata->irq_chip.unmask_base = pdata->irq_base + SPRD_PMIC_INT_EN;
   227		ddata->irq_chip.ack_base = 0;
   228		ddata->irq_chip.num_regs = 1;
   229		ddata->irq_chip.num_irqs = pdata->num_irqs;
   230	
   231		ddata->irqs = devm_kcalloc(&spi->dev,
   232					   pdata->num_irqs, sizeof(struct regmap_irq),
   233					   GFP_KERNEL);
   234		if (!ddata->irqs)
   235			return -ENOMEM;
   236	
   237		ddata->irq_chip.irqs = ddata->irqs;
   238		for (i = 0; i < pdata->num_irqs; i++)
   239			ddata->irqs[i].mask = BIT(i);
   240	
   241		ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq,
   242					       IRQF_ONESHOT, 0,
   243					       &ddata->irq_chip, &ddata->irq_data);
   244		if (ret) {
   245			dev_err(&spi->dev, "Failed to add PMIC irq chip %d\n", ret);
   246			return ret;
   247		}
   248	
   249		ret = devm_mfd_add_devices(&spi->dev, PLATFORM_DEVID_AUTO,
   250					   cells, num_cells, NULL, 0,
   251					   regmap_irq_get_domain(ddata->irq_data));
   252		if (ret) {
   253			dev_err(&spi->dev, "Failed to populate sub-devices %d\n", ret);
   254			return ret;
   255		}
   256	
   257		ret = devm_device_init_wakeup(&spi->dev);
   258		if (ret)
   259			return dev_err_probe(&spi->dev, ret, "Failed to init wakeup\n");
   260	
   261		return 0;
   262	}
   263	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki