diff options
Diffstat (limited to 'drivers/mfd/rohm-bd718x7.c')
| -rw-r--r-- | drivers/mfd/rohm-bd718x7.c | 166 |
1 files changed, 98 insertions, 68 deletions
diff --git a/drivers/mfd/rohm-bd718x7.c b/drivers/mfd/rohm-bd718x7.c index a29d529a96f4..ff714fd4f54d 100644 --- a/drivers/mfd/rohm-bd718x7.c +++ b/drivers/mfd/rohm-bd718x7.c @@ -14,7 +14,7 @@ #include <linux/mfd/rohm-bd718x7.h> #include <linux/mfd/core.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/types.h> @@ -30,14 +30,24 @@ static struct gpio_keys_platform_data bd718xx_powerkey_data = { .name = "bd718xx-pwrkey", }; -static struct mfd_cell bd718xx_mfd_cells[] = { +static struct mfd_cell bd71837_mfd_cells[] = { { .name = "gpio-keys", .platform_data = &bd718xx_powerkey_data, .pdata_size = sizeof(bd718xx_powerkey_data), }, - { .name = "bd718xx-clk", }, - { .name = "bd718xx-pmic", }, + { .name = "bd71837-clk", }, + { .name = "bd71837-pmic", }, +}; + +static struct mfd_cell bd71847_mfd_cells[] = { + { + .name = "gpio-keys", + .platform_data = &bd718xx_powerkey_data, + .pdata_size = sizeof(bd718xx_powerkey_data), + }, + { .name = "bd71847-clk", }, + { .name = "bd71847-pmic", }, }; static const struct regmap_irq bd718xx_irqs[] = { @@ -50,7 +60,7 @@ static const struct regmap_irq bd718xx_irqs[] = { REGMAP_IRQ_REG(BD718XX_INT_STBY_REQ, 0, BD718XX_INT_STBY_REQ_MASK), }; -static struct regmap_irq_chip bd718xx_irq_chip = { +static const struct regmap_irq_chip bd718xx_irq_chip = { .name = "bd718xx-irq", .irqs = bd718xx_irqs, .num_irqs = ARRAY_SIZE(bd718xx_irqs), @@ -60,17 +70,15 @@ static struct regmap_irq_chip bd718xx_irq_chip = { .mask_base = BD718XX_REG_MIRQ, .ack_base = BD718XX_REG_IRQ, .init_ack_masked = true, - .mask_invert = false, }; -static const struct regmap_range pmic_status_range = { - .range_min = BD718XX_REG_IRQ, - .range_max = BD718XX_REG_POW_STATE, +static const struct regmap_range pmic_status_range[] = { + regmap_reg_range(BD718XX_REG_IRQ, BD718XX_REG_POW_STATE), }; static const struct regmap_access_table volatile_regs = { - .yes_ranges = &pmic_status_range, - .n_yes_ranges = 1, + .yes_ranges = &pmic_status_range[0], + .n_yes_ranges = ARRAY_SIZE(pmic_status_range), }; static const struct regmap_config bd718xx_regmap_config = { @@ -78,83 +86,101 @@ static const struct regmap_config bd718xx_regmap_config = { .val_bits = 8, .volatile_table = &volatile_regs, .max_register = BD718XX_MAX_REGISTER - 1, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; -static int bd718xx_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int bd718xx_init_press_duration(struct regmap *regmap, + struct device *dev) { - struct bd718xx *bd718xx; + u32 short_press_ms, long_press_ms; + u32 short_press_value, long_press_value; int ret; - if (!i2c->irq) { - dev_err(&i2c->dev, "No IRQ configured\n"); - return -EINVAL; + ret = of_property_read_u32(dev->of_node, "rohm,short-press-ms", + &short_press_ms); + if (!ret) { + short_press_value = min(15u, (short_press_ms + 250) / 500); + ret = regmap_update_bits(regmap, BD718XX_REG_PWRONCONFIG0, + BD718XX_PWRBTN_PRESS_DURATION_MASK, + short_press_value); + if (ret) { + dev_err(dev, "Failed to init pwron short press\n"); + return ret; + } } - bd718xx = devm_kzalloc(&i2c->dev, sizeof(struct bd718xx), GFP_KERNEL); + ret = of_property_read_u32(dev->of_node, "rohm,long-press-ms", + &long_press_ms); + if (!ret) { + long_press_value = min(15u, (long_press_ms + 500) / 1000); + ret = regmap_update_bits(regmap, BD718XX_REG_PWRONCONFIG1, + BD718XX_PWRBTN_PRESS_DURATION_MASK, + long_press_value); + if (ret) { + dev_err(dev, "Failed to init pwron long press\n"); + return ret; + } + } - if (!bd718xx) - return -ENOMEM; + return 0; +} - bd718xx->chip_irq = i2c->irq; - bd718xx->chip_type = (unsigned int)(uintptr_t) - of_device_get_match_data(&i2c->dev); - bd718xx->dev = &i2c->dev; - dev_set_drvdata(&i2c->dev, bd718xx); +static int bd718xx_i2c_probe(struct i2c_client *i2c) +{ + struct regmap *regmap; + struct regmap_irq_chip_data *irq_data; + int ret; + unsigned int chip_type; + struct mfd_cell *mfd; + int cells; - bd718xx->regmap = devm_regmap_init_i2c(i2c, &bd718xx_regmap_config); - if (IS_ERR(bd718xx->regmap)) { - dev_err(&i2c->dev, "regmap initialization failed\n"); - return PTR_ERR(bd718xx->regmap); + if (!i2c->irq) { + dev_err(&i2c->dev, "No IRQ configured\n"); + return -EINVAL; } - - ret = devm_regmap_add_irq_chip(&i2c->dev, bd718xx->regmap, - bd718xx->chip_irq, IRQF_ONESHOT, 0, - &bd718xx_irq_chip, &bd718xx->irq_data); - if (ret) { - dev_err(&i2c->dev, "Failed to add irq_chip\n"); - return ret; + chip_type = (unsigned int)(uintptr_t) + of_device_get_match_data(&i2c->dev); + switch (chip_type) { + case ROHM_CHIP_TYPE_BD71837: + mfd = bd71837_mfd_cells; + cells = ARRAY_SIZE(bd71837_mfd_cells); + break; + case ROHM_CHIP_TYPE_BD71847: + mfd = bd71847_mfd_cells; + cells = ARRAY_SIZE(bd71847_mfd_cells); + break; + default: + dev_err(&i2c->dev, "Unknown device type"); + return -EINVAL; } - /* Configure short press to 10 milliseconds */ - ret = regmap_update_bits(bd718xx->regmap, - BD718XX_REG_PWRONCONFIG0, - BD718XX_PWRBTN_PRESS_DURATION_MASK, - BD718XX_PWRBTN_SHORT_PRESS_10MS); - if (ret) { - dev_err(&i2c->dev, - "Failed to configure button short press timeout\n"); - return ret; - } + regmap = devm_regmap_init_i2c(i2c, &bd718xx_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(&i2c->dev, PTR_ERR(regmap), + "regmap initialization failed\n"); - /* Configure long press to 10 seconds */ - ret = regmap_update_bits(bd718xx->regmap, - BD718XX_REG_PWRONCONFIG1, - BD718XX_PWRBTN_PRESS_DURATION_MASK, - BD718XX_PWRBTN_LONG_PRESS_10S); + ret = devm_regmap_add_irq_chip(&i2c->dev, regmap, i2c->irq, + IRQF_ONESHOT, 0, &bd718xx_irq_chip, + &irq_data); + if (ret) + return dev_err_probe(&i2c->dev, ret, "Failed to add irq_chip\n"); - if (ret) { - dev_err(&i2c->dev, - "Failed to configure button long press timeout\n"); + ret = bd718xx_init_press_duration(regmap, &i2c->dev); + if (ret) return ret; - } - ret = regmap_irq_get_virq(bd718xx->irq_data, BD718XX_INT_PWRBTN_S); + ret = regmap_irq_get_virq(irq_data, BD718XX_INT_PWRBTN_S); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to get the IRQ\n"); - return ret; - } + if (ret < 0) + return dev_err_probe(&i2c->dev, ret, "Failed to get the IRQ\n"); button.irq = ret; - ret = devm_mfd_add_devices(bd718xx->dev, PLATFORM_DEVID_AUTO, - bd718xx_mfd_cells, - ARRAY_SIZE(bd718xx_mfd_cells), NULL, 0, - regmap_irq_get_domain(bd718xx->irq_data)); + ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, + mfd, cells, NULL, 0, + regmap_irq_get_domain(irq_data)); if (ret) - dev_err(&i2c->dev, "Failed to create subdevices\n"); + dev_err_probe(&i2c->dev, ret, "Failed to create subdevices\n"); return ret; } @@ -162,11 +188,15 @@ static int bd718xx_i2c_probe(struct i2c_client *i2c, static const struct of_device_id bd718xx_of_match[] = { { .compatible = "rohm,bd71837", - .data = (void *)BD718XX_TYPE_BD71837, + .data = (void *)ROHM_CHIP_TYPE_BD71837, }, { .compatible = "rohm,bd71847", - .data = (void *)BD718XX_TYPE_BD71847, + .data = (void *)ROHM_CHIP_TYPE_BD71847, + }, + { + .compatible = "rohm,bd71850", + .data = (void *)ROHM_CHIP_TYPE_BD71847, }, { } }; |
