diff options
author | Ryo Kataoka <ryo.kataoka.wt@renesas.com> | 2019-03-22 20:50:37 +0900 |
---|---|---|
committer | Ryo Kataoka <ryo.kataoka.wt@renesas.com> | 2019-03-22 20:50:37 +0900 |
commit | c3cbd3684e52686f65a24baa9ea5803c557c4d67 (patch) | |
tree | 6c675e590a8ba41e42740560d0fcf6b882b5b25d | |
parent | 538d41278caaf9b4066db035a11c4ef38f5912f3 (diff) | |
parent | a9181365a599574b10df01cabdfc7c4e1cb222c3 (diff) | |
download | renesas-bsp-c3cbd3684e52686f65a24baa9ea5803c557c4d67.tar.gz |
Merge branch 'rcar-3.9.2/bd9571MWV.rc4' into v4.14.75-ltsi/rcar-3.9.3
* rcar-3.9.2/bd9571MWV.rc4:
mfd: bd9571mwv: Clean up the BD9574MWF register mapping
mfd: bd9571mwv: Enable GPIO support for PMIC BD9574MWF
mfd: bd9571mwv: fix section mismatch
mfd: bd9571mwv: Add support for BD9574MWF
mfd: bd9571mwv: Make the driver more generic
-rw-r--r-- | drivers/mfd/bd9571mwv.c | 168 | ||||
-rw-r--r-- | include/linux/mfd/bd9571mwv.h | 14 | ||||
-rw-r--r-- | include/linux/mfd/bd9574mwf.h | 100 |
3 files changed, 260 insertions, 22 deletions
diff --git a/drivers/mfd/bd9571mwv.c b/drivers/mfd/bd9571mwv.c index 98192d4863e4c..91ec49637e7b6 100644 --- a/drivers/mfd/bd9571mwv.c +++ b/drivers/mfd/bd9571mwv.c @@ -2,6 +2,7 @@ * ROHM BD9571MWV-M MFD driver * * Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com> + * Copyright (C) 2019 Renesas Electronics Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 as @@ -21,12 +22,20 @@ #include <linux/module.h> #include <linux/mfd/bd9571mwv.h> +#include <linux/mfd/bd9574mwf.h> static const struct mfd_cell bd9571mwv_cells[] = { { .name = "bd9571mwv-regulator", }, { .name = "bd9571mwv-gpio", }, }; +static const struct mfd_cell bd9574mwf_cells[] = { + { .name = "bd9571mwv-gpio", }, +}; + +static const struct bd957x_data *bd_data; + +/* 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_AVS_SET_MONI, BD9571MWV_AVS_DVFS_VID(3)), @@ -108,6 +117,108 @@ static struct regmap_irq_chip bd9571mwv_irq_chip = { .num_irqs = ARRAY_SIZE(bd9571mwv_irqs), }; +/* 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), +}; + +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 bd9571mwv_data = { + .product_code_val = BD9571MWV_PRODUCT_CODE_VAL, + .part_number = BD9571MWV_PART_NUMBER, + .regmap_config = &bd9571mwv_regmap_config, + .irq_chip = &bd9571mwv_irq_chip, +}; + +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, +}; + +static const struct of_device_id bd9571mwv_of_match_table[] = { + { .compatible = "rohm,bd9571mwv", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, bd9571mwv_of_match_table); + +static const struct i2c_device_id bd9571mwv_id_table[] = { + { "bd9571mwv", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, bd9571mwv_id_table); + static int bd9571mwv_identify(struct bd9571mwv *bd) { struct device *dev = bd->dev; @@ -133,13 +244,12 @@ static int bd9571mwv_identify(struct bd9571mwv *bd) ret); return ret; } - - if (value != BD9571MWV_PRODUCT_CODE_VAL) { + /* Confirm the product code */ + if (value != bd_data->product_code_val) { dev_err(dev, "Invalid product code ID %02x (expected %02x)\n", - value, BD9571MWV_PRODUCT_CODE_VAL); + value, bd_data->product_code_val); return -EINVAL; } - ret = regmap_read(bd->regmap, BD9571MWV_PRODUCT_REVISION, &value); if (ret) { dev_err(dev, "Failed to read revision register (ret=%i)\n", @@ -147,7 +257,8 @@ static int bd9571mwv_identify(struct bd9571mwv *bd) return ret; } - dev_info(dev, "Device: BD9571MWV rev. %d\n", value & 0xff); + dev_info(dev, "Device: %s rev. %d\n", bd_data->part_number, + value & 0xff); return 0; } @@ -156,6 +267,7 @@ static int bd9571mwv_probe(struct i2c_client *client, const struct i2c_device_id *ids) { struct bd9571mwv *bd; + unsigned int product_code; int ret; bd = devm_kzalloc(&client->dev, sizeof(*bd), GFP_KERNEL); @@ -166,7 +278,23 @@ static int bd9571mwv_probe(struct i2c_client *client, bd->dev = &client->dev; bd->irq = client->irq; - bd->regmap = devm_regmap_init_i2c(client, &bd9571mwv_regmap_config); + /* Read the PMIC product code */ + ret = i2c_smbus_read_byte_data(client, BD9571MWV_PRODUCT_CODE); + if (ret < 0) { + dev_err(&client->dev, "failed reading at 0x%02x\n", + BD9571MWV_PRODUCT_CODE); + return ret; + } + + product_code = (unsigned int)ret; + + /* Init data for PMIC device base on product code */ + if (product_code == BD9571MWV_PRODUCT_CODE_VAL) + bd_data = &bd9571mwv_data; + else + bd_data = &bd9574mwf_data; + + bd->regmap = devm_regmap_init_i2c(client, bd_data->regmap_config); if (IS_ERR(bd->regmap)) { dev_err(bd->dev, "Failed to initialize register map\n"); return PTR_ERR(bd->regmap); @@ -177,15 +305,23 @@ static int bd9571mwv_probe(struct i2c_client *client, return ret; ret = regmap_add_irq_chip(bd->regmap, bd->irq, IRQF_ONESHOT, 0, - &bd9571mwv_irq_chip, &bd->irq_data); + bd_data->irq_chip, &bd->irq_data); if (ret) { dev_err(bd->dev, "Failed to register IRQ chip\n"); return ret; } - ret = mfd_add_devices(bd->dev, PLATFORM_DEVID_AUTO, bd9571mwv_cells, - ARRAY_SIZE(bd9571mwv_cells), NULL, 0, - regmap_irq_get_domain(bd->irq_data)); + if (product_code == BD9571MWV_PRODUCT_CODE_VAL) { + ret = mfd_add_devices(bd->dev, PLATFORM_DEVID_AUTO, + bd9571mwv_cells, + ARRAY_SIZE(bd9571mwv_cells), NULL, 0, + regmap_irq_get_domain(bd->irq_data)); + } else { + ret = mfd_add_devices(bd->dev, PLATFORM_DEVID_AUTO, + bd9574mwf_cells, + ARRAY_SIZE(bd9574mwf_cells), NULL, 0, + regmap_irq_get_domain(bd->irq_data)); + } if (ret) { regmap_del_irq_chip(bd->irq, bd->irq_data); return ret; @@ -203,18 +339,6 @@ static int bd9571mwv_remove(struct i2c_client *client) return 0; } -static const struct of_device_id bd9571mwv_of_match_table[] = { - { .compatible = "rohm,bd9571mwv", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, bd9571mwv_of_match_table); - -static const struct i2c_device_id bd9571mwv_id_table[] = { - { "bd9571mwv", 0 }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(i2c, bd9571mwv_id_table); - static struct i2c_driver bd9571mwv_driver = { .driver = { .name = "bd9571mwv", diff --git a/include/linux/mfd/bd9571mwv.h b/include/linux/mfd/bd9571mwv.h index f0708ba4cbbae..8b14126e86025 100644 --- a/include/linux/mfd/bd9571mwv.h +++ b/include/linux/mfd/bd9571mwv.h @@ -2,6 +2,7 @@ * ROHM BD9571MWV-M driver * * Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com> + * Copyright (C) 2019 Renesas Electronics Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 as @@ -86,6 +87,8 @@ #define BD9571MWV_ACCESS_KEY 0xff +#define BD9571MWV_PART_NUMBER "BD9571MWV" + /* Define the BD9571MWV IRQ numbers */ enum bd9571mwv_irqs { BD9571MWV_IRQ_MD1, @@ -112,4 +115,15 @@ struct bd9571mwv { struct regmap_irq_chip_data *irq_data; }; +/** + * struct bd957x_data - internal data for the bd957x driver + * + * Internal data to distinguish bd9571mwv chip and bd9574mwf chip + */ +struct bd957x_data { + int product_code_val; + char *part_number; + const struct regmap_config *regmap_config; + const struct regmap_irq_chip *irq_chip; +}; #endif /* __LINUX_MFD_BD9571MWV_H */ diff --git a/include/linux/mfd/bd9574mwf.h b/include/linux/mfd/bd9574mwf.h new file mode 100644 index 0000000000000..977c23be4a634 --- /dev/null +++ b/include/linux/mfd/bd9574mwf.h @@ -0,0 +1,100 @@ +/* + * ROHM BD9574MWF-M driver + * + * Copyright (C) 2019 Renesas Electronics Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether expressed or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + */ + +#ifndef __LINUX_MFD_BD9574MWF_H +#define __LINUX_MFD_BD9574MWF_H + +/* 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, +}; + +#endif /* __LINUX_MFD_BD9574MWF_H */ |