Re: [PATCH 3/3] mfd: bd9571mwv: Add support for BD9574MWF

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2020-12-08 at 17:04 +0900, Yoshihiro Shimoda wrote:
> From: Khiem Nguyen <khiem.nguyen.xt@xxxxxxxxxxx>
> 
> The new PMIC BD9574MWF inherits features from BD9571MWV.
> Add the support of new PMIC to existing bd9571mwv driver.
> 
> Signed-off-by: Khiem Nguyen <khiem.nguyen.xt@xxxxxxxxxxx>
> [shimoda: rebase and refactor]
> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx>
> ---
>  drivers/mfd/bd9571mwv.c       | 92
> +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/bd9571mwv.h | 80
> +++++++++++++++++++++++++++++++++++++
>  2 files changed, 172 insertions(+)
> 
> diff --git a/drivers/mfd/bd9571mwv.c b/drivers/mfd/bd9571mwv.c
> index 57bdb6a..f8f0a87 100644
> --- a/drivers/mfd/bd9571mwv.c
> +++ b/drivers/mfd/bd9571mwv.c
> @@ -20,6 +20,7 @@ static const struct mfd_cell bd9571mwv_cells[] = {
>  	{ .name = "bd9571mwv-gpio", },
>  };
>  
> +/* Regmap for BD9571MWV */
>  static const struct regmap_range bd9571mwv_readable_yes_ranges[] = {
>  	regmap_reg_range(BD9571MWV_VENDOR_CODE,
> BD9571MWV_PRODUCT_REVISION),
>  	regmap_reg_range(BD9571MWV_BKUP_MODE_CNT,
> BD9571MWV_BKUP_MODE_CNT),
> @@ -112,6 +113,95 @@ static const struct bd957x_data bd9571mwv_data =
> {
>  	.num_cells = ARRAY_SIZE(bd9571mwv_cells),
>  };
>  
> +static const struct mfd_cell bd9574mwf_cells[] = {
> +	{ .name = "bd9571mwv-gpio", },

Another 'nit' suggestion which you can ignore if it does not make sense
:)

Are the GPIO blocks 100% identical? If not, then I would suggest
changing this to:
{ .name = "bd9574mwf-gpio", },

and populating the platform_driver id_table for sub driver(s) using
something like:

static const struct platform_device_id bd957x_gpio_id[] = {
        { "bd9571mwv-gpio", ROHM_CHIP_TYPE_BD9571 },
        { "bd9574mwf-gpio", ROHM_CHIP_TYPE_BD9574 },
        { },
};

Then you can get the IC type using
platform_get_device_id(pdev)->driver_data.

Next, I think the parent data from MFD is only used to get the regmap
and dev in sub-devices, right? Maybe you could simplify this and get
rid of the whole MFD parent data structure? I think you can use

pdev->dev.parent to get the parent device and
dev_get_regmap(pdev->dev.parent, NULL);

to get the regmap?

(After this I wonder if you need the
struct bd9571mwv at all?)

> +};
> +
> +/* Regmap for BD9574MWF */
> +static const struct regmap_range bd9574mwf_readable_yes_ranges[] = {
> +	regmap_reg_range(BD9574MWF_VENDOR_CODE,
> BD9574MWF_PRODUCT_REVISION),
> +	regmap_reg_range(BD9574MWF_GPIO_IN, BD9574MWF_GPIO_IN),
> +	regmap_reg_range(BD9574MWF_GPIO_INT, BD9574MWF_GPIO_INTMASK),
> +	regmap_reg_range(BD9574MWF_GPIO_MUX, BD9574MWF_GPIO_MUX),
> +	regmap_reg_range(BD9574MWF_INT_INTREQ, BD9574MWF_INT_INTMASK),
> +};
> +
> +static const struct regmap_access_table bd9574mwf_readable_table = {
> +	.yes_ranges	= bd9574mwf_readable_yes_ranges,
> +	.n_yes_ranges	= ARRAY_SIZE(bd9574mwf_readable_yes_ranges),
> +};
> +
> +static const struct regmap_range bd9574mwf_writable_yes_ranges[] = {
> +	regmap_reg_range(BD9574MWF_GPIO_DIR, BD9574MWF_GPIO_OUT),
> +	regmap_reg_range(BD9574MWF_GPIO_INT_SET,
> BD9574MWF_GPIO_INTMASK),
> +	regmap_reg_range(BD9574MWF_INT_INTREQ, BD9574MWF_INT_INTMASK),
> +};
> +
> +static const struct regmap_access_table bd9574mwf_writable_table = {
> +	.yes_ranges	= bd9574mwf_writable_yes_ranges,
> +	.n_yes_ranges	= ARRAY_SIZE(bd9574mwf_writable_yes_ranges),
> +};
> +
> +static const struct regmap_range bd9574mwf_volatile_yes_ranges[] = {
> +	regmap_reg_range(BD9574MWF_GPIO_IN, BD9574MWF_GPIO_IN),
> +	regmap_reg_range(BD9574MWF_GPIO_INT, BD9574MWF_GPIO_INT),
> +	regmap_reg_range(BD9574MWF_INT_INTREQ, BD9574MWF_INT_INTREQ),
> +};

Are you using the other interrupts/statuses or VDCORE MoniVDAC? Should
they be volatile too?

> +
> +static const struct regmap_access_table bd9574mwf_volatile_table = {
> +	.yes_ranges	= bd9574mwf_volatile_yes_ranges,
> +	.n_yes_ranges	= ARRAY_SIZE(bd9574mwf_volatile_yes_ranges),
> +};
> +
> +static const struct regmap_config bd9574mwf_regmap_config = {
> +	.reg_bits	= 8,
> +	.val_bits	= 8,
> +	.cache_type	= REGCACHE_RBTREE,
> +	.rd_table	= &bd9574mwf_readable_table,
> +	.wr_table	= &bd9574mwf_writable_table,
> +	.volatile_table	= &bd9574mwf_volatile_table,
> +	.max_register	= 0xff,
> +};
> +
> +static const struct regmap_irq bd9574mwf_irqs[] = {
> +	REGMAP_IRQ_REG(BD9574MWF_IRQ_MD1, 0,
> +		       BD9574MWF_INT_INTREQ_MD1_INT),
> +	REGMAP_IRQ_REG(BD9574MWF_IRQ_MD2_E1, 0,
> +		       BD9574MWF_INT_INTREQ_MD2_E1_INT),
> +	REGMAP_IRQ_REG(BD9574MWF_IRQ_MD2_E2, 0,
> +		       BD9574MWF_INT_INTREQ_MD2_E2_INT),
> +	REGMAP_IRQ_REG(BD9574MWF_IRQ_PROT_ERR, 0,
> +		       BD9574MWF_INT_INTREQ_PROT_ERR_INT),
> +	REGMAP_IRQ_REG(BD9574MWF_IRQ_GP, 0,
> +		       BD9574MWF_INT_INTREQ_GP_INT),
> +	REGMAP_IRQ_REG(BD9574MWF_IRQ_BKUP_HOLD_OF, 0,
> +		       BD9574MWF_INT_INTREQ_BKUP_HOLD_OF_INT),
> +	REGMAP_IRQ_REG(BD9574MWF_IRQ_WDT_OF, 0,
> +		       BD9574MWF_INT_INTREQ_WDT_OF_INT),
> +	REGMAP_IRQ_REG(BD9574MWF_IRQ_BKUP_TRG, 0,
> +		       BD9574MWF_INT_INTREQ_BKUP_TRG_INT),
> +};
> +
> +static struct regmap_irq_chip bd9574mwf_irq_chip = {
> +	.name		= "bd9574mwf",
> +	.status_base	= BD9574MWF_INT_INTREQ,
> +	.mask_base	= BD9574MWF_INT_INTMASK,
> +	.ack_base	= BD9574MWF_INT_INTREQ,
> +	.init_ack_masked = true,
> +	.num_regs	= 1,
> +	.irqs		= bd9574mwf_irqs,
> +	.num_irqs	= ARRAY_SIZE(bd9574mwf_irqs),
> +};
> +
> +static const struct bd957x_data bd9574mwf_data = {
> +	.product_code_val = BD9574MWF_PRODUCT_CODE_VAL,
> +	.part_number = BD9574MWF_PART_NUMBER,
> +	.regmap_config = &bd9574mwf_regmap_config,
> +	.irq_chip = &bd9574mwf_irq_chip,
> +	.cells = bd9574mwf_cells,
> +	.num_cells = ARRAY_SIZE(bd9574mwf_cells),
> +};
> +
>  static int bd9571mwv_identify(struct bd9571mwv *bd)
>  {
>  	struct device *dev = bd->dev;
> @@ -182,6 +272,8 @@ static int bd9571mwv_probe(struct i2c_client
> *client,
>  	product_code = (unsigned int)ret;
>  	if (product_code == BD9571MWV_PRODUCT_CODE_VAL)
>  		bd->data = &bd9571mwv_data;
> +	else if (product_code == BD9574MWF_PRODUCT_CODE_VAL)
> +		bd->data = &bd9574mwf_data;
>  
>  	if (!bd->data) {
>  		dev_err(bd->dev, "No found supported device %d\n",
> diff --git a/include/linux/mfd/bd9571mwv.h
> b/include/linux/mfd/bd9571mwv.h
> index 0126b52..e9e219b 100644
> --- a/include/linux/mfd/bd9571mwv.h
> +++ b/include/linux/mfd/bd9571mwv.h
> @@ -99,6 +99,86 @@ enum bd9571mwv_irqs {
>  	BD9571MWV_IRQ_BKUP_TRG,
>  };
>  
> +/* List of registers for BD9574MWF */
> +#define BD9574MWF_VENDOR_CODE			0x00
> +#define BD9574MWF_VENDOR_CODE_VAL		0xdb
> +#define BD9574MWF_PRODUCT_CODE			0x01
> +#define BD9574MWF_PRODUCT_CODE_VAL		0x74
> +#define BD9574MWF_PRODUCT_REVISION		0x02
> +
> +#define BD9574MWF_I2C_FUSA_MODE			0x10
> +#define BD9574MWF_I2C_MD2_E1_BIT_1		0x11
> +#define BD9574MWF_I2C_MD2_E1_BIT_2		0x12
> +
> +#define BD9574MWF_BKUP_MODE_CNT			0x20
> +#define BD9574MWF_BKUP_MODE_STATUS		0x21
> +#define BD9574MWF_BKUP_RECOVERY_CNT		0x22
> +#define BD9574MWF_BKUP_CTRL_TIM_CNT		0x23
> +#define BD9574MWF_WAITBKUP_WDT_CNT		0x24
> +#define BD9574MWF_BKUP_HOLD_TIM_CNT1		0x26
> +#define BD9574MWF_QLLM_CNT			0x27
> +#define BD9574MWF_BKUP_HOLD_TIM_CNT2		0x28
> +
> +#define BD9574MWF_DCDC_FREQ			0x48
> +
> +#define BD9574MWF_VDCORE_VINIT			0x50
> +#define BD9574MWF_VD09_VINIT			0x51
> +#define BD9574MWF_VDCORE_SETVMAX		0x52
> +#define BD9574MWF_VDCORE_SETVID			0x54
> +#define BD9574MWF_VDCORE_MONIVDAC		0x55
> +#define BD9574MWF_VDCORE_PGD_CNT		0x56
> +
> +#define BD9574MWF_GPIO_DIR			0x60
> +#define BD9574MWF_GPIO_OUT			0x61
> +#define BD9574MWF_GPIO_IN			0x62
> +#define BD9574MWF_GPIO_DEB			0x63
> +#define BD9574MWF_GPIO_INT_SET			0x64
> +#define BD9574MWF_GPIO_INT			0x65
> +#define BD9574MWF_GPIO_INTMASK			0x66
> +#define BD9574MWF_GPIO_MUX			0x67
> +
> +#define BD9574MWF_REG_KEEP(n)			(0x70 + (n))
> +
> +#define BD9574MWF_PMIC_INTERNAL_STATUS		0x80
> +#define BD9574MWF_PROT_ERROR_STATUS0		0x81
> +#define BD9574MWF_PROT_ERROR_STATUS1		0x82
> +#define BD9574MWF_PROT_ERROR_STATUS2		0x83
> +#define BD9574MWF_PROT_ERROR_STATUS3		0x84
> +#define BD9574MWF_PROT_ERROR_STATUS4		0x85
> +#define BD9574MWF_PROT_ERROR_STATUS5		0x86
> +#define BD9574MWF_SYS_ERROR_STATUS		0x87
> +
> +#define BD9574MWF_INT_INTREQ			0x90
> +#define BD9574MWF_INT_INTREQ_MD1_INT		BIT(0)
> +#define BD9574MWF_INT_INTREQ_MD2_E1_INT		BIT(1)
> +#define BD9574MWF_INT_INTREQ_MD2_E2_INT		BIT(2)
> +#define BD9574MWF_INT_INTREQ_PROT_ERR_INT	BIT(3)
> +#define BD9574MWF_INT_INTREQ_GP_INT		BIT(4)
> +#define BD9574MWF_INT_INTREQ_BKUP_HOLD_OF_INT	BIT(5)
> +#define BD9574MWF_INT_INTREQ_WDT_OF_INT		BIT(6)
> +#define BD9574MWF_INT_INTREQ_BKUP_TRG_INT	BIT(7)
> +#define BD9574MWF_INT_INTMASK			0x91
> +
> +#define BD9574MWF_SSCG_CNT			0xA0
> +#define BD9574MWF_POFFB_MRB			0xA1
> +#define BD9574MWF_SMRB_WR_PROT			0xA2
> +#define BD9574MWF_SMRB_ASSERT			0xA3
> +#define BD9574MWF_SMRB_STATUS			0xA4
> +
> +#define BD9574MWF_PART_NUMBER			"BD9574MWF"
> +
> +/* Define the BD9574MWF IRQ numbers */
> +enum bd9574mwf_irqs {
> +	BD9574MWF_IRQ_MD1,
> +	BD9574MWF_IRQ_MD2_E1,
> +	BD9574MWF_IRQ_MD2_E2,
> +	BD9574MWF_IRQ_PROT_ERR,
> +	BD9574MWF_IRQ_GP,
> +	BD9574MWF_IRQ_BKUP_HOLD_OF,
> +	BD9574MWF_IRQ_WDT_OF,
> +	BD9574MWF_IRQ_BKUP_TRG,
> +};
> +
>  /**
>   * struct bd957x_data - internal data for the bd957x driver
>   *

Overall a good looking driver! Thanks a lot!

Best Regards
    Matti

--
Matti Vaittinen, Linux device drivers
ROHM Semiconductors, Finland SWDC
Kiviharjunlenkki 1E
90220 OULU
FINLAND

~~~ "I don't think so," said Rene Descartes. Just then he vanished ~~~

Simon says - in Latin please.
"non cogito me" dixit Rene Descarte, deinde evanescavit

(Thanks for the translation Simon)






[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux