On Wed, Apr 5, 2017 at 11:03 PM, Icenowy Zheng <[email protected]> wrote:
>
>
> 在 2017年04月05日 22:58, Chen-Yu Tsai 写道:
>>
>> On Wed, Apr 5, 2017 at 2:01 AM, Icenowy Zheng <[email protected]> wrote:
>>>
>>> AXP803 is a new PMIC chip produced by X-Powers, usually paired with A64
>>> via RSB bus. The PMIC itself is like AXP288, but with RSB support and
>>> dedicated VBUS and ACIN.
>>>
>>> Add support for it in the axp20x mfd driver.
>>>
>>> Currently only power key function is supported.
>>>
>>> Signed-off-by: Icenowy Zheng <[email protected]>
>>> ---
>>>  drivers/mfd/axp20x-rsb.c   |   1 +
>>>  drivers/mfd/axp20x.c       | 113
>>> +++++++++++++++++++++++++++++++++++++++++++++
>>>  include/linux/mfd/axp20x.h |  40 +++++++++++++++-
>>>  3 files changed, 153 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/mfd/axp20x-rsb.c b/drivers/mfd/axp20x-rsb.c
>>> index a732cb50bcff..3ff8a7d1ce88 100644
>>> --- a/drivers/mfd/axp20x-rsb.c
>>> +++ b/drivers/mfd/axp20x-rsb.c
>>> @@ -63,6 +63,7 @@ static const struct of_device_id axp20x_rsb_of_match[]
>>> = {
>>>         { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
>>>         { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
>>>         { .compatible = "x-powers,axp809", .data = (void *)AXP809_ID },
>>> +       { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
>>
>>
>> As mentioned in the previous patches, please sort them in ascending order.
>>
>>>         { },
>>>  };
>>>  MODULE_DEVICE_TABLE(of, axp20x_rsb_of_match);
>>> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
>>> index 5ba3b04cc9b1..e468e08d84db 100644
>>> --- a/drivers/mfd/axp20x.c
>>> +++ b/drivers/mfd/axp20x.c
>>> @@ -43,6 +43,7 @@ static const char * const axp20x_model_names[] = {
>>>         "AXP288",
>>>         "AXP806",
>>>         "AXP809",
>>> +       "AXP803",
>>
>>
>> Same here.
>>
>>>  };
>>>
>>>  static const struct regmap_range axp152_writeable_ranges[] = {
>>> @@ -165,6 +166,32 @@ static const struct regmap_access_table
>>> axp806_volatile_table = {
>>>         .n_yes_ranges   = ARRAY_SIZE(axp806_volatile_ranges),
>>>  };
>>>
>>> +static const struct regmap_range axp803_writeable_ranges[] = {
>>> +       regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),
>>> +       regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),
>>> +};
>>> +
>>> +static const struct regmap_range axp803_volatile_ranges[] = {
>>> +       regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP288_POWER_REASON),
>>> +       regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL),
>>> +       regmap_reg_range(AXP288_BC_DET_STAT, AXP288_BC_DET_STAT),
>>> +       regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
>>> +       regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
>>> +       regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
>>> +       regmap_reg_range(AXP288_RT_BATT_V_H, AXP288_RT_BATT_V_L),
>>> +       regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
>>> +};
>>> +
>>> +static const struct regmap_access_table axp803_writeable_table = {
>>> +       .yes_ranges     = axp803_writeable_ranges,
>>> +       .n_yes_ranges   = ARRAY_SIZE(axp803_writeable_ranges),
>>> +};
>>> +
>>> +static const struct regmap_access_table axp803_volatile_table = {
>>> +       .yes_ranges     = axp803_volatile_ranges,
>>> +       .n_yes_ranges   = ARRAY_SIZE(axp803_volatile_ranges),
>>> +};
>>> +
>>
>>
>> If they are the same as the AXP288, please just use that set,
>> instead of duplicating it. You can add a note, like what I did
>> for the AXP22x/AXP809.
>>
>>>  static struct resource axp152_pek_resources[] = {
>>>         DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
>>>         DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
>>> @@ -278,6 +305,20 @@ static struct resource axp809_pek_resources[] = {
>>>         },
>>>  };
>>>
>>> +static struct resource axp803_pek_resources[] = {
>>> +       {
>>> +               .name   = "PEK_DBR",
>>> +               .start  = AXP803_IRQ_PEK_RIS_EDGE,
>>> +               .end    = AXP803_IRQ_PEK_RIS_EDGE,
>>> +               .flags  = IORESOURCE_IRQ,
>>> +       }, {
>>> +               .name   = "PEK_DBF",
>>> +               .start  = AXP803_IRQ_PEK_FAL_EDGE,
>>> +               .end    = AXP803_IRQ_PEK_FAL_EDGE,
>>> +               .flags  = IORESOURCE_IRQ,
>>> +       },
>>> +};
>>> +
>>
>>
>> You can use axp288_power_button_resources directly. See below
>> about the interrupts and symbol names.
>>
>>>  static const struct regmap_config axp152_regmap_config = {
>>>         .reg_bits       = 8,
>>>         .val_bits       = 8,
>>> @@ -323,6 +364,15 @@ static const struct regmap_config
>>> axp806_regmap_config = {
>>>         .cache_type     = REGCACHE_RBTREE,
>>>  };
>>>
>>> +static const struct regmap_config axp803_regmap_config = {
>>> +       .reg_bits       = 8,
>>> +       .val_bits       = 8,
>>> +       .wr_table       = &axp803_writeable_table,
>>> +       .volatile_table = &axp803_volatile_table,
>>> +       .max_register   = AXP288_FG_TUNE5,
>>> +       .cache_type     = REGCACHE_RBTREE,
>>> +};
>>> +
>>
>>
>> Drop this and use axp288_regmap_config.
>>
>>>  #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask)                   \
>>>         [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask =
>>> BIT(_mask) }
>>>
>>> @@ -507,6 +557,43 @@ static const struct regmap_irq axp809_regmap_irqs[]
>>> = {
>>>         INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT,            4, 0),
>>>  };
>>>
>>> +static const struct regmap_irq axp803_regmap_irqs[] = {
>>> +       INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V,            0, 7),
>>> +       INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN,            0, 6),
>>> +       INIT_REGMAP_IRQ(AXP803, ACIN_REMOVAL,           0, 5),
>>> +       INIT_REGMAP_IRQ(AXP803, VBUS_OVER_V,            0, 4),
>>> +       INIT_REGMAP_IRQ(AXP803, VBUS_PLUGIN,            0, 3),
>>> +       INIT_REGMAP_IRQ(AXP803, VBUS_REMOVAL,           0, 2),
>>> +       INIT_REGMAP_IRQ(AXP803, BATT_PLUGIN,            1, 7),
>>> +       INIT_REGMAP_IRQ(AXP803, BATT_REMOVAL,           1, 6),
>>> +       INIT_REGMAP_IRQ(AXP803, BATT_ENT_ACT_MODE,      1, 5),
>>> +       INIT_REGMAP_IRQ(AXP803, BATT_EXIT_ACT_MODE,     1, 4),
>>> +       INIT_REGMAP_IRQ(AXP803, CHARG,                  1, 3),
>>> +       INIT_REGMAP_IRQ(AXP803, CHARG_DONE,             1, 2),
>>> +       INIT_REGMAP_IRQ(AXP803, BATT_CHG_TEMP_HIGH,     2, 7),
>>> +       INIT_REGMAP_IRQ(AXP803, BATT_CHG_TEMP_HIGH_END, 2, 6),
>>> +       INIT_REGMAP_IRQ(AXP803, BATT_CHG_TEMP_LOW,      2, 5),
>>> +       INIT_REGMAP_IRQ(AXP803, BATT_CHG_TEMP_LOW_END,  2, 4),
>>> +       INIT_REGMAP_IRQ(AXP803, BATT_ACT_TEMP_HIGH,     2, 3),
>>> +       INIT_REGMAP_IRQ(AXP803, BATT_ACT_TEMP_HIGH_END, 2, 2),
>>> +       INIT_REGMAP_IRQ(AXP803, BATT_ACT_TEMP_LOW,      2, 1),
>>> +       INIT_REGMAP_IRQ(AXP803, BATT_ACT_TEMP_LOW_END,  2, 0),
>>> +       INIT_REGMAP_IRQ(AXP803, DIE_TEMP_HIGH,          3, 7),
>>> +       INIT_REGMAP_IRQ(AXP803, GPADC,                  3, 2),
>>> +       INIT_REGMAP_IRQ(AXP803, LOW_PWR_LVL1,           3, 1),
>>> +       INIT_REGMAP_IRQ(AXP803, LOW_PWR_LVL2,           3, 0),
>>> +       INIT_REGMAP_IRQ(AXP803, TIMER,                  4, 7),
>>> +       INIT_REGMAP_IRQ(AXP803, PEK_RIS_EDGE,           4, 6),
>>> +       INIT_REGMAP_IRQ(AXP803, PEK_FAL_EDGE,           4, 5),
>>> +       INIT_REGMAP_IRQ(AXP803, PEK_SHORT,              4, 4),
>>> +       INIT_REGMAP_IRQ(AXP803, PEK_LONG,               4, 3),
>>> +       INIT_REGMAP_IRQ(AXP803, PEK_OVER_OFF,           4, 2),
>>> +       INIT_REGMAP_IRQ(AXP803, GPIO1_INPUT,            4, 1),
>>> +       INIT_REGMAP_IRQ(AXP803, GPIO0_INPUT,            4, 0),
>>> +       INIT_REGMAP_IRQ(AXP803, BC_USB_CHNG,            5, 1),
>>> +       INIT_REGMAP_IRQ(AXP803, MV_CHNG,                5, 0),
>>> +};
>>> +
>>
>>
>> Looks like the same set as AXP288, albeit with different names.
>> Please use that set instead of duplicating it. The different naming
>> scheme is OK, as the symbols really only get used when defining
>> resources for the various sub-devices.
>
>
> Some functions are different.
>
> AXP288 doesn't feature the division of VBUS and ACIN, but AXP803
> does.

You're right. Keep the interrupts separate then.

ChenYu

>>
>>>  static const struct regmap_irq_chip axp152_regmap_irq_chip = {
>>>         .name                   = "axp152_irq_chip",
>>>         .status_base            = AXP152_IRQ1_STATE,
>>> @@ -581,6 +668,18 @@ static const struct regmap_irq_chip
>>> axp809_regmap_irq_chip = {
>>>         .num_regs               = 5,
>>>  };
>>>
>>> +static const struct regmap_irq_chip axp803_regmap_irq_chip = {
>>> +       .name                   = "axp803",
>>> +       .status_base            = AXP20X_IRQ1_STATE,
>>> +       .ack_base               = AXP20X_IRQ1_STATE,
>>> +       .mask_base              = AXP20X_IRQ1_EN,
>>> +       .mask_invert            = true,
>>> +       .init_ack_masked        = true,
>>> +       .irqs                   = axp803_regmap_irqs,
>>> +       .num_irqs               = ARRAY_SIZE(axp803_regmap_irqs),
>>> +       .num_regs               = 6,
>>> +};
>>> +
>>
>>
>> Same here.
>>
>> In general we want to be able to share as much as possible.
>> Otherwise we'd just have separate drivers.
>>
>> Regards
>> ChenYu
>>
>>>  static struct mfd_cell axp20x_cells[] = {
>>>         {
>>>                 .name           = "axp20x-gpio",
>>> @@ -787,6 +886,14 @@ static struct mfd_cell axp809_cells[] = {
>>>         },
>>>  };
>>>
>>> +static struct mfd_cell axp803_cells[] = {
>>> +       {
>>> +               .name                   = "axp20x-pek",
>>> +               .num_resources          =
>>> ARRAY_SIZE(axp803_pek_resources),
>>> +               .resources              = axp803_pek_resources,
>>> +       }
>>> +};
>>> +
>>>  static struct axp20x_dev *axp20x_pm_power_off;
>>>  static void axp20x_power_off(void)
>>>  {
>>> @@ -867,6 +974,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
>>>                 axp20x->regmap_cfg = &axp22x_regmap_config;
>>>                 axp20x->regmap_irq_chip = &axp809_regmap_irq_chip;
>>>                 break;
>>> +       case AXP803_ID:
>>> +               axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
>>> +               axp20x->cells = axp803_cells;
>>> +               axp20x->regmap_cfg = &axp803_regmap_config;
>>> +               axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
>>> +               break;
>>>         default:
>>>                 dev_err(dev, "unsupported AXP20X ID %lu\n",
>>> axp20x->variant);
>>>                 return -EINVAL;
>>> diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
>>> index dc8798cf2a24..b3220ef374d3 100644
>>> --- a/include/linux/mfd/axp20x.h
>>> +++ b/include/linux/mfd/axp20x.h
>>> @@ -22,6 +22,7 @@ enum axp20x_variants {
>>>         AXP288_ID,
>>>         AXP806_ID,
>>>         AXP809_ID,
>>> +       AXP803_ID,
>>>         NR_AXP20X_VARIANTS,
>>>  };
>>>
>>> @@ -234,7 +235,7 @@ enum axp20x_variants {
>>>  #define AXP22X_TS_ADC_L                        0x59
>>>  #define AXP22X_BATLOW_THRES1           0xe6
>>>
>>> -/* AXP288 specific registers */
>>> +/* AXP288/AXP803 specific registers */
>>>  #define AXP288_POWER_REASON            0x02
>>>  #define AXP288_BC_GLOBAL               0x2c
>>>  #define AXP288_BC_VBUS_CNTL            0x2d
>>> @@ -525,6 +526,43 @@ enum axp809_irqs {
>>>         AXP809_IRQ_GPIO0_INPUT,
>>>  };
>>>
>>> +enum axp803_irqs {
>>> +       AXP803_IRQ_ACIN_OVER_V = 1,
>>> +       AXP803_IRQ_ACIN_PLUGIN,
>>> +       AXP803_IRQ_ACIN_REMOVAL,
>>> +       AXP803_IRQ_VBUS_OVER_V,
>>> +       AXP803_IRQ_VBUS_PLUGIN,
>>> +       AXP803_IRQ_VBUS_REMOVAL,
>>> +       AXP803_IRQ_BATT_PLUGIN,
>>> +       AXP803_IRQ_BATT_REMOVAL,
>>> +       AXP803_IRQ_BATT_ENT_ACT_MODE,
>>> +       AXP803_IRQ_BATT_EXIT_ACT_MODE,
>>> +       AXP803_IRQ_CHARG,
>>> +       AXP803_IRQ_CHARG_DONE,
>>> +       AXP803_IRQ_BATT_CHG_TEMP_HIGH,
>>> +       AXP803_IRQ_BATT_CHG_TEMP_HIGH_END,
>>> +       AXP803_IRQ_BATT_CHG_TEMP_LOW,
>>> +       AXP803_IRQ_BATT_CHG_TEMP_LOW_END,
>>> +       AXP803_IRQ_BATT_ACT_TEMP_HIGH,
>>> +       AXP803_IRQ_BATT_ACT_TEMP_HIGH_END,
>>> +       AXP803_IRQ_BATT_ACT_TEMP_LOW,
>>> +       AXP803_IRQ_BATT_ACT_TEMP_LOW_END,
>>> +       AXP803_IRQ_DIE_TEMP_HIGH,
>>> +       AXP803_IRQ_GPADC,
>>> +       AXP803_IRQ_LOW_PWR_LVL1,
>>> +       AXP803_IRQ_LOW_PWR_LVL2,
>>> +       AXP803_IRQ_TIMER,
>>> +       AXP803_IRQ_PEK_RIS_EDGE,
>>> +       AXP803_IRQ_PEK_FAL_EDGE,
>>> +       AXP803_IRQ_PEK_SHORT,
>>> +       AXP803_IRQ_PEK_LONG,
>>> +       AXP803_IRQ_PEK_OVER_OFF,
>>> +       AXP803_IRQ_GPIO1_INPUT,
>>> +       AXP803_IRQ_GPIO0_INPUT,
>>> +       AXP803_IRQ_BC_USB_CHNG,
>>> +       AXP803_IRQ_MV_CHNG,
>>> +};
>>> +
>>>  struct axp20x_dev {
>>>         struct device                   *dev;
>>>         int                             irq;
>>> --
>>> 2.12.2
>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups
>>> "linux-sunxi" group.
>>> To unsubscribe from this group and stop receiving emails from it, send an
>>> email to [email protected].
>>> For more options, visit https://groups.google.com/d/optout.
>>
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to