diff mbox series

[v2,4/7] hw/misc: Allwinner AXP-209 Emulation

Message ID 20221218211918.3592-5-strahinja.p.jankovic@gmail.com (mailing list archive)
State New, archived
Headers show
Series Enable Cubieboard A10 boot SPL from SD card | expand

Commit Message

Strahinja Jankovic Dec. 18, 2022, 9:19 p.m. UTC
This patch adds minimal support for AXP-209 PMU.
Most important is chip ID since U-Boot SPL expects version 0x1. Besides
the chip ID register, reset values for two more registers used by A10
U-Boot SPL are covered.

Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
---
 hw/arm/Kconfig              |   1 +
 hw/misc/Kconfig             |   4 +
 hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
 hw/misc/meson.build         |   1 +
 hw/misc/trace-events        |   5 +
 5 files changed, 249 insertions(+)
 create mode 100644 hw/misc/allwinner-axp-209.c

Comments

Strahinja Jankovic Dec. 18, 2022, 9:28 p.m. UTC | #1
I forgot to add Philippe Mathieu-Daudé in CC for this patch, so I'm
fixing it now.

Best regards,
Strahinja Jankovic

On Sun, Dec 18, 2022 at 10:19 PM Strahinja Jankovic
<strahinjapjankovic@gmail.com> wrote:
>
> This patch adds minimal support for AXP-209 PMU.
> Most important is chip ID since U-Boot SPL expects version 0x1. Besides
> the chip ID register, reset values for two more registers used by A10
> U-Boot SPL are covered.
>
> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> ---
>  hw/arm/Kconfig              |   1 +
>  hw/misc/Kconfig             |   4 +
>  hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
>  hw/misc/meson.build         |   1 +
>  hw/misc/trace-events        |   5 +
>  5 files changed, 249 insertions(+)
>  create mode 100644 hw/misc/allwinner-axp-209.c
>
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index eefe1fd134..67c6e83fe6 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -323,6 +323,7 @@ config ALLWINNER_A10
>      select ALLWINNER_A10_DRAMC
>      select ALLWINNER_EMAC
>      select ALLWINNER_I2C
> +    select ALLWINNER_AXP_209
>      select SERIAL
>      select UNIMP
>
> diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> index 052fb54310..3855d937fd 100644
> --- a/hw/misc/Kconfig
> +++ b/hw/misc/Kconfig
> @@ -180,4 +180,8 @@ config ALLWINNER_A10_CCM
>  config ALLWINNER_A10_DRAMC
>      bool
>
> +config ALLWINNER_AXP_209
> +    bool
> +    depends on I2C
> +
>  source macio/Kconfig
> diff --git a/hw/misc/allwinner-axp-209.c b/hw/misc/allwinner-axp-209.c
> new file mode 100644
> index 0000000000..cf79175034
> --- /dev/null
> +++ b/hw/misc/allwinner-axp-209.c
> @@ -0,0 +1,238 @@
> +/*
> + * AXP-209 Emulation
> + *
> + * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * SPDX-License-Identifier: MIT
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "trace.h"
> +#include "hw/i2c/i2c.h"
> +#include "migration/vmstate.h"
> +
> +#define TYPE_AXP_209 "allwinner.axp209"
> +
> +#define AXP_209(obj) \
> +    OBJECT_CHECK(AXP209I2CState, (obj), TYPE_AXP_209)
> +
> +/* registers */
> +enum {
> +    REG_POWER_STATUS = 0x0u,
> +    REG_OPERATING_MODE,
> +    REG_OTG_VBUS_STATUS,
> +    REG_CHIP_VERSION,
> +    REG_DATA_CACHE_0,
> +    REG_DATA_CACHE_1,
> +    REG_DATA_CACHE_2,
> +    REG_DATA_CACHE_3,
> +    REG_DATA_CACHE_4,
> +    REG_DATA_CACHE_5,
> +    REG_DATA_CACHE_6,
> +    REG_DATA_CACHE_7,
> +    REG_DATA_CACHE_8,
> +    REG_DATA_CACHE_9,
> +    REG_DATA_CACHE_A,
> +    REG_DATA_CACHE_B,
> +    REG_POWER_OUTPUT_CTRL = 0x12u,
> +    REG_DC_DC2_OUT_V_CTRL = 0x23u,
> +    REG_DC_DC2_DVS_CTRL = 0x25u,
> +    REG_DC_DC3_OUT_V_CTRL = 0x27u,
> +    REG_LDO2_4_OUT_V_CTRL,
> +    REG_LDO3_OUT_V_CTRL,
> +    REG_VBUS_CH_MGMT = 0x30u,
> +    REG_SHUTDOWN_V_CTRL,
> +    REG_SHUTDOWN_CTRL,
> +    REG_CHARGE_CTRL_1,
> +    REG_CHARGE_CTRL_2,
> +    REG_SPARE_CHARGE_CTRL,
> +    REG_PEK_KEY_CTRL,
> +    REG_DC_DC_FREQ_SET,
> +    REG_CHR_TEMP_TH_SET,
> +    REG_CHR_HIGH_TEMP_TH_CTRL,
> +    REG_IPSOUT_WARN_L1,
> +    REG_IPSOUT_WARN_L2,
> +    REG_DISCHR_TEMP_TH_SET,
> +    REG_DISCHR_HIGH_TEMP_TH_CTRL,
> +    REG_IRQ_BANK_1_CTRL = 0x40u,
> +    REG_IRQ_BANK_2_CTRL,
> +    REG_IRQ_BANK_3_CTRL,
> +    REG_IRQ_BANK_4_CTRL,
> +    REG_IRQ_BANK_5_CTRL,
> +    REG_IRQ_BANK_1_STAT = 0x48u,
> +    REG_IRQ_BANK_2_STAT,
> +    REG_IRQ_BANK_3_STAT,
> +    REG_IRQ_BANK_4_STAT,
> +    REG_IRQ_BANK_5_STAT,
> +    REG_ADC_ACIN_V_H = 0x56u,
> +    REG_ADC_ACIN_V_L,
> +    REG_ADC_ACIN_CURR_H,
> +    REG_ADC_ACIN_CURR_L,
> +    REG_ADC_VBUS_V_H,
> +    REG_ADC_VBUS_V_L,
> +    REG_ADC_VBUS_CURR_H,
> +    REG_ADC_VBUS_CURR_L,
> +    REG_ADC_INT_TEMP_H,
> +    REG_ADC_INT_TEMP_L,
> +    REG_ADC_TEMP_SENS_V_H = 0x62u,
> +    REG_ADC_TEMP_SENS_V_L,
> +    REG_ADC_BAT_V_H = 0x78u,
> +    REG_ADC_BAT_V_L,
> +    REG_ADC_BAT_DISCHR_CURR_H,
> +    REG_ADC_BAT_DISCHR_CURR_L,
> +    REG_ADC_BAT_CHR_CURR_H,
> +    REG_ADC_BAT_CHR_CURR_L,
> +    REG_ADC_IPSOUT_V_H,
> +    REG_ADC_IPSOUT_V_L,
> +    REG_DC_DC_MOD_SEL = 0x80u,
> +    REG_ADC_EN_1,
> +    REG_ADC_EN_2,
> +    REG_ADC_SR_CTRL,
> +    REG_ADC_IN_RANGE,
> +    REG_GPIO1_ADC_IRQ_RISING_TH,
> +    REG_GPIO1_ADC_IRQ_FALLING_TH,
> +    REG_TIMER_CTRL = 0x8au,
> +    REG_VBUS_CTRL_MON_SRP,
> +    REG_OVER_TEMP_SHUTDOWN = 0x8fu,
> +    REG_GPIO0_FEAT_SET,
> +    REG_GPIO_OUT_HIGH_SET,
> +    REG_GPIO1_FEAT_SET,
> +    REG_GPIO2_FEAT_SET,
> +    REG_GPIO_SIG_STATE_SET_MON,
> +    REG_GPIO3_SET,
> +    REG_COULOMB_CNTR_CTRL = 0xb8u,
> +    REG_POWER_MEAS_RES,
> +    NR_REGS
> +};
> +
> +#define AXP_209_CHIP_VERSION_ID             (0x01)
> +#define AXP_209_DC_DC2_OUT_V_CTRL_RESET     (0x16)
> +#define AXP_209_IRQ_BANK_1_CTRL_RESET       (0xd8)
> +
> +/* A simple I2C slave which returns values of ID or CNT register. */
> +typedef struct AXP209I2CState {
> +    /*< private >*/
> +    I2CSlave i2c;
> +    /*< public >*/
> +    uint8_t regs[NR_REGS];  /* peripheral registers */
> +    uint8_t ptr;            /* current register index */
> +    uint8_t count;          /* counter used for tx/rx */
> +} AXP209I2CState;
> +
> +/* Reset all counters and load ID register */
> +static void axp_209_reset_enter(Object *obj, ResetType type)
> +{
> +    AXP209I2CState *s = AXP_209(obj);
> +
> +    memset(s->regs, 0, NR_REGS);
> +    s->ptr = 0;
> +    s->count = 0;
> +    s->regs[REG_CHIP_VERSION] = AXP_209_CHIP_VERSION_ID;
> +    s->regs[REG_DC_DC2_OUT_V_CTRL] = AXP_209_DC_DC2_OUT_V_CTRL_RESET;
> +    s->regs[REG_IRQ_BANK_1_CTRL] = AXP_209_IRQ_BANK_1_CTRL_RESET;
> +}
> +
> +/* Handle events from master. */
> +static int axp_209_event(I2CSlave *i2c, enum i2c_event event)
> +{
> +    AXP209I2CState *s = AXP_209(i2c);
> +
> +    s->count = 0;
> +
> +    return 0;
> +}
> +
> +/* Called when master requests read */
> +static uint8_t axp_209_rx(I2CSlave *i2c)
> +{
> +    AXP209I2CState *s = AXP_209(i2c);
> +    uint8_t ret = 0xff;
> +
> +    if (s->ptr < NR_REGS) {
> +        ret = s->regs[s->ptr++];
> +    }
> +
> +    trace_allwinner_axp_209_rx(s->ptr - 1, ret);
> +
> +    return ret;
> +}
> +
> +/*
> + * Called when master sends write.
> + * Update ptr with byte 0, then perform write with second byte.
> + */
> +static int axp_209_tx(I2CSlave *i2c, uint8_t data)
> +{
> +    AXP209I2CState *s = AXP_209(i2c);
> +
> +    if (s->count == 0) {
> +        /* Store register address */
> +        s->ptr = data;
> +        s->count++;
> +        trace_allwinner_axp_209_select(data);
> +    } else {
> +        trace_allwinner_axp_209_tx(s->ptr, data);
> +        if (s->ptr == REG_DC_DC2_OUT_V_CTRL) {
> +            s->regs[s->ptr++] = data;
> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +static const VMStateDescription vmstate_axp_209 = {
> +    .name = TYPE_AXP_209,
> +    .version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT8_ARRAY(regs, AXP209I2CState, NR_REGS),
> +        VMSTATE_UINT8(count, AXP209I2CState),
> +        VMSTATE_UINT8(ptr, AXP209I2CState),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void axp_209_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +    I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc);
> +    ResettableClass *rc = RESETTABLE_CLASS(oc);
> +
> +    rc->phases.enter = axp_209_reset_enter;
> +    dc->vmsd = &vmstate_axp_209;
> +    isc->event = axp_209_event;
> +    isc->recv = axp_209_rx;
> +    isc->send = axp_209_tx;
> +}
> +
> +static const TypeInfo axp_209_info = {
> +    .name = TYPE_AXP_209,
> +    .parent = TYPE_I2C_SLAVE,
> +    .instance_size = sizeof(AXP209I2CState),
> +    .class_init = axp_209_class_init
> +};
> +
> +static void axp_209_register_devices(void)
> +{
> +    type_register_static(&axp_209_info);
> +}
> +
> +type_init(axp_209_register_devices);
> diff --git a/hw/misc/meson.build b/hw/misc/meson.build
> index 9eaa0750b5..7d332851cb 100644
> --- a/hw/misc/meson.build
> +++ b/hw/misc/meson.build
> @@ -40,6 +40,7 @@ softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
>
>  softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
>  softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_DRAMC', if_true: files('allwinner-a10-dramc.c'))
> +softmmu_ss.add(when: 'CONFIG_ALLWINNER_AXP_209', if_true: files('allwinner-axp-209.c'))
>  softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
>  specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'))
>  softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
> diff --git a/hw/misc/trace-events b/hw/misc/trace-events
> index c18bc0605e..f6a7a6901f 100644
> --- a/hw/misc/trace-events
> +++ b/hw/misc/trace-events
> @@ -1,5 +1,10 @@
>  # See docs/devel/tracing.rst for syntax documentation.
>
> +# allwinner-axp209.c
> +allwinner_axp_209_rx(uint8_t reg, uint8_t data) "Read reg 0x%" PRIx8 " : 0x%" PRIx8
> +allwinner_axp_209_select(uint8_t reg) "Accessing reg 0x%" PRIx8
> +allwinner_axp_209_tx(uint8_t reg, uint8_t data) "Write reg 0x%" PRIx8 " : 0x%" PRIx8
> +
>  # allwinner-cpucfg.c
>  allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_addr 0x%" PRIx32
>  allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
> --
> 2.30.2
>
Philippe Mathieu-Daudé Dec. 18, 2022, 10:07 p.m. UTC | #2
On 18/12/22 22:19, Strahinja Jankovic wrote:
> This patch adds minimal support for AXP-209 PMU.
> Most important is chip ID since U-Boot SPL expects version 0x1. Besides
> the chip ID register, reset values for two more registers used by A10
> U-Boot SPL are covered.
> 
> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> ---
>   hw/arm/Kconfig              |   1 +
>   hw/misc/Kconfig             |   4 +
>   hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
>   hw/misc/meson.build         |   1 +
>   hw/misc/trace-events        |   5 +
>   5 files changed, 249 insertions(+)
>   create mode 100644 hw/misc/allwinner-axp-209.c


> diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> index 052fb54310..3855d937fd 100644
> --- a/hw/misc/Kconfig
> +++ b/hw/misc/Kconfig
> @@ -180,4 +180,8 @@ config ALLWINNER_A10_CCM
>   config ALLWINNER_A10_DRAMC
>       bool
>   
> +config ALLWINNER_AXP_209

This controller is not specific to AllWinner. It can be plugged on any
i2c bus. Please rename it AXP209_PMU. Otherwise LGTM!

> +    bool
> +    depends on I2C
> +
>   source macio/Kconfig
> diff --git a/hw/misc/allwinner-axp-209.c b/hw/misc/allwinner-axp-209.c
> new file mode 100644
> index 0000000000..cf79175034
> --- /dev/null
> +++ b/hw/misc/allwinner-axp-209.c
> @@ -0,0 +1,238 @@
> +/*
> + * AXP-209 Emulation
> + *
> + * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
Strahinja Jankovic Dec. 18, 2022, 10:12 p.m. UTC | #3
Hi,

On Sun, Dec 18, 2022 at 11:07 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> On 18/12/22 22:19, Strahinja Jankovic wrote:
> > This patch adds minimal support for AXP-209 PMU.
> > Most important is chip ID since U-Boot SPL expects version 0x1. Besides
> > the chip ID register, reset values for two more registers used by A10
> > U-Boot SPL are covered.
> >
> > Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> > ---
> >   hw/arm/Kconfig              |   1 +
> >   hw/misc/Kconfig             |   4 +
> >   hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
> >   hw/misc/meson.build         |   1 +
> >   hw/misc/trace-events        |   5 +
> >   5 files changed, 249 insertions(+)
> >   create mode 100644 hw/misc/allwinner-axp-209.c
>
>
> > diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> > index 052fb54310..3855d937fd 100644
> > --- a/hw/misc/Kconfig
> > +++ b/hw/misc/Kconfig
> > @@ -180,4 +180,8 @@ config ALLWINNER_A10_CCM
> >   config ALLWINNER_A10_DRAMC
> >       bool
> >
> > +config ALLWINNER_AXP_209
>
> This controller is not specific to AllWinner. It can be plugged on any
> i2c bus. Please rename it AXP209_PMU. Otherwise LGTM!

Do you mean only in Kconfig, or everywhere (file name, function names,
etc.)? Thanks.

Best regards,
Strahinja


>
> > +    bool
> > +    depends on I2C
> > +
> >   source macio/Kconfig
> > diff --git a/hw/misc/allwinner-axp-209.c b/hw/misc/allwinner-axp-209.c
> > new file mode 100644
> > index 0000000000..cf79175034
> > --- /dev/null
> > +++ b/hw/misc/allwinner-axp-209.c
> > @@ -0,0 +1,238 @@
> > +/*
> > + * AXP-209 Emulation
> > + *
> > + * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
Philippe Mathieu-Daudé Dec. 18, 2022, 10:23 p.m. UTC | #4
On 18/12/22 23:12, Strahinja Jankovic wrote:
> Hi,
> 
> On Sun, Dec 18, 2022 at 11:07 PM Philippe Mathieu-Daudé
> <philmd@linaro.org> wrote:
>>
>> On 18/12/22 22:19, Strahinja Jankovic wrote:
>>> This patch adds minimal support for AXP-209 PMU.
>>> Most important is chip ID since U-Boot SPL expects version 0x1. Besides
>>> the chip ID register, reset values for two more registers used by A10
>>> U-Boot SPL are covered.
>>>
>>> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
>>> ---
>>>    hw/arm/Kconfig              |   1 +
>>>    hw/misc/Kconfig             |   4 +
>>>    hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
>>>    hw/misc/meson.build         |   1 +
>>>    hw/misc/trace-events        |   5 +
>>>    5 files changed, 249 insertions(+)
>>>    create mode 100644 hw/misc/allwinner-axp-209.c
>>
>>
>>> diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
>>> index 052fb54310..3855d937fd 100644
>>> --- a/hw/misc/Kconfig
>>> +++ b/hw/misc/Kconfig
>>> @@ -180,4 +180,8 @@ config ALLWINNER_A10_CCM
>>>    config ALLWINNER_A10_DRAMC
>>>        bool
>>>
>>> +config ALLWINNER_AXP_209
>>
>> This controller is not specific to AllWinner. It can be plugged on any
>> i2c bus. Please rename it AXP209_PMU. Otherwise LGTM!
> 
> Do you mean only in Kconfig, or everywhere (file name, function names,
> etc.)? Thanks.

Keeping the file / functions names with 'allwinner' would give the false
idea this is AllWinner specific; rather confusing isn't it? Besides it
is not part of the SoC, this is an external component sitting on the
bus. So "everywhere".

Also, the "select ALLWINNER_AXP_209/AXP209_PMU" line in hw/arm/Kconfig
belongs to the next patch "hw/arm: Add AXP-209 to Cubieboard".

Regards,

Phil.
Strahinja Jankovic Dec. 18, 2022, 10:39 p.m. UTC | #5
Hi,

On Sun, Dec 18, 2022 at 11:23 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> On 18/12/22 23:12, Strahinja Jankovic wrote:
> > Hi,
> >
> > On Sun, Dec 18, 2022 at 11:07 PM Philippe Mathieu-Daudé
> > <philmd@linaro.org> wrote:
> >>
> >> On 18/12/22 22:19, Strahinja Jankovic wrote:
> >>> This patch adds minimal support for AXP-209 PMU.
> >>> Most important is chip ID since U-Boot SPL expects version 0x1. Besides
> >>> the chip ID register, reset values for two more registers used by A10
> >>> U-Boot SPL are covered.
> >>>
> >>> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> >>> ---
> >>>    hw/arm/Kconfig              |   1 +
> >>>    hw/misc/Kconfig             |   4 +
> >>>    hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
> >>>    hw/misc/meson.build         |   1 +
> >>>    hw/misc/trace-events        |   5 +
> >>>    5 files changed, 249 insertions(+)
> >>>    create mode 100644 hw/misc/allwinner-axp-209.c
> >>
> >>
> >>> diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> >>> index 052fb54310..3855d937fd 100644
> >>> --- a/hw/misc/Kconfig
> >>> +++ b/hw/misc/Kconfig
> >>> @@ -180,4 +180,8 @@ config ALLWINNER_A10_CCM
> >>>    config ALLWINNER_A10_DRAMC
> >>>        bool
> >>>
> >>> +config ALLWINNER_AXP_209
> >>
> >> This controller is not specific to AllWinner. It can be plugged on any
> >> i2c bus. Please rename it AXP209_PMU. Otherwise LGTM!
> >
> > Do you mean only in Kconfig, or everywhere (file name, function names,
> > etc.)? Thanks.
>
> Keeping the file / functions names with 'allwinner' would give the false
> idea this is AllWinner specific; rather confusing isn't it? Besides it
> is not part of the SoC, this is an external component sitting on the
> bus. So "everywhere".

I was expecting that answer, but I wanted to check :)
When I started writing code for AXP209 it was indeed without allwinner
prefix, but then checkpatch.pl complained about missing lines in
MAINTAINERS. At that time it was easier to add the prefix (and get a
match in MAINTAINERS) than to investigate if I should update the
MAINTAINERS file or ignore the checkpatch.pl complaint.

I will update everything related to AXP209 so it does not have the
Allwinner prefix.

>
> Also, the "select ALLWINNER_AXP_209/AXP209_PMU" line in hw/arm/Kconfig
> belongs to the next patch "hw/arm: Add AXP-209 to Cubieboard".

I agree, will fix it.

Best regards,
Strahinja

>
> Regards,
>
> Phil.
Philippe Mathieu-Daudé Dec. 19, 2022, 7:15 a.m. UTC | #6
On 18/12/22 23:39, Strahinja Jankovic wrote:
> Hi,
> 
> On Sun, Dec 18, 2022 at 11:23 PM Philippe Mathieu-Daudé
> <philmd@linaro.org> wrote:
>>
>> On 18/12/22 23:12, Strahinja Jankovic wrote:
>>> Hi,
>>>
>>> On Sun, Dec 18, 2022 at 11:07 PM Philippe Mathieu-Daudé
>>> <philmd@linaro.org> wrote:
>>>>
>>>> On 18/12/22 22:19, Strahinja Jankovic wrote:
>>>>> This patch adds minimal support for AXP-209 PMU.
>>>>> Most important is chip ID since U-Boot SPL expects version 0x1. Besides
>>>>> the chip ID register, reset values for two more registers used by A10
>>>>> U-Boot SPL are covered.
>>>>>
>>>>> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
>>>>> ---
>>>>>     hw/arm/Kconfig              |   1 +
>>>>>     hw/misc/Kconfig             |   4 +
>>>>>     hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
>>>>>     hw/misc/meson.build         |   1 +
>>>>>     hw/misc/trace-events        |   5 +
>>>>>     5 files changed, 249 insertions(+)
>>>>>     create mode 100644 hw/misc/allwinner-axp-209.c


>>>>> +config ALLWINNER_AXP_209
>>>>
>>>> This controller is not specific to AllWinner. It can be plugged on any
>>>> i2c bus. Please rename it AXP209_PMU. Otherwise LGTM!
>>>
>>> Do you mean only in Kconfig, or everywhere (file name, function names,
>>> etc.)? Thanks.
>>
>> Keeping the file / functions names with 'allwinner' would give the false
>> idea this is AllWinner specific; rather confusing isn't it? Besides it
>> is not part of the SoC, this is an external component sitting on the
>> bus. So "everywhere".
> 
> I was expecting that answer, but I wanted to check :)
> When I started writing code for AXP209 it was indeed without allwinner
> prefix, but then checkpatch.pl complained about missing lines in
> MAINTAINERS. At that time it was easier to add the prefix (and get a
> match in MAINTAINERS) than to investigate if I should update the
> MAINTAINERS file or ignore the checkpatch.pl complaint.
> 
> I will update everything related to AXP209 so it does not have the
> Allwinner prefix.

Add a new AXP209 MAINTAINERS's section with your name :) Or add the new
file to the Allwinner-a10 section and add your name as designated
reviewer or co-maintainer :)
Strahinja Jankovic Dec. 19, 2022, 10:05 p.m. UTC | #7
On Mon, Dec 19, 2022 at 8:15 AM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> On 18/12/22 23:39, Strahinja Jankovic wrote:
> > Hi,
> >
> > On Sun, Dec 18, 2022 at 11:23 PM Philippe Mathieu-Daudé
> > <philmd@linaro.org> wrote:
> >>
> >> On 18/12/22 23:12, Strahinja Jankovic wrote:
> >>> Hi,
> >>>
> >>> On Sun, Dec 18, 2022 at 11:07 PM Philippe Mathieu-Daudé
> >>> <philmd@linaro.org> wrote:
> >>>>
> >>>> On 18/12/22 22:19, Strahinja Jankovic wrote:
> >>>>> This patch adds minimal support for AXP-209 PMU.
> >>>>> Most important is chip ID since U-Boot SPL expects version 0x1. Besides
> >>>>> the chip ID register, reset values for two more registers used by A10
> >>>>> U-Boot SPL are covered.
> >>>>>
> >>>>> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> >>>>> ---
> >>>>>     hw/arm/Kconfig              |   1 +
> >>>>>     hw/misc/Kconfig             |   4 +
> >>>>>     hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
> >>>>>     hw/misc/meson.build         |   1 +
> >>>>>     hw/misc/trace-events        |   5 +
> >>>>>     5 files changed, 249 insertions(+)
> >>>>>     create mode 100644 hw/misc/allwinner-axp-209.c
>
>
> >>>>> +config ALLWINNER_AXP_209
> >>>>
> >>>> This controller is not specific to AllWinner. It can be plugged on any
> >>>> i2c bus. Please rename it AXP209_PMU. Otherwise LGTM!
> >>>
> >>> Do you mean only in Kconfig, or everywhere (file name, function names,
> >>> etc.)? Thanks.
> >>
> >> Keeping the file / functions names with 'allwinner' would give the false
> >> idea this is AllWinner specific; rather confusing isn't it? Besides it
> >> is not part of the SoC, this is an external component sitting on the
> >> bus. So "everywhere".
> >
> > I was expecting that answer, but I wanted to check :)
> > When I started writing code for AXP209 it was indeed without allwinner
> > prefix, but then checkpatch.pl complained about missing lines in
> > MAINTAINERS. At that time it was easier to add the prefix (and get a
> > match in MAINTAINERS) than to investigate if I should update the
> > MAINTAINERS file or ignore the checkpatch.pl complaint.
> >
> > I will update everything related to AXP209 so it does not have the
> > Allwinner prefix.
>
> Add a new AXP209 MAINTAINERS's section with your name :) Or add the new
> file to the Allwinner-a10 section and add your name as designated
> reviewer or co-maintainer :)

Thanks, I will take one of these suggested approaches.

Best regards,
Strahinja
diff mbox series

Patch

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index eefe1fd134..67c6e83fe6 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -323,6 +323,7 @@  config ALLWINNER_A10
     select ALLWINNER_A10_DRAMC
     select ALLWINNER_EMAC
     select ALLWINNER_I2C
+    select ALLWINNER_AXP_209
     select SERIAL
     select UNIMP
 
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 052fb54310..3855d937fd 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -180,4 +180,8 @@  config ALLWINNER_A10_CCM
 config ALLWINNER_A10_DRAMC
     bool
 
+config ALLWINNER_AXP_209
+    bool
+    depends on I2C
+
 source macio/Kconfig
diff --git a/hw/misc/allwinner-axp-209.c b/hw/misc/allwinner-axp-209.c
new file mode 100644
index 0000000000..cf79175034
--- /dev/null
+++ b/hw/misc/allwinner-axp-209.c
@@ -0,0 +1,238 @@ 
+/*
+ * AXP-209 Emulation
+ *
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "hw/i2c/i2c.h"
+#include "migration/vmstate.h"
+
+#define TYPE_AXP_209 "allwinner.axp209"
+
+#define AXP_209(obj) \
+    OBJECT_CHECK(AXP209I2CState, (obj), TYPE_AXP_209)
+
+/* registers */
+enum {
+    REG_POWER_STATUS = 0x0u,
+    REG_OPERATING_MODE,
+    REG_OTG_VBUS_STATUS,
+    REG_CHIP_VERSION,
+    REG_DATA_CACHE_0,
+    REG_DATA_CACHE_1,
+    REG_DATA_CACHE_2,
+    REG_DATA_CACHE_3,
+    REG_DATA_CACHE_4,
+    REG_DATA_CACHE_5,
+    REG_DATA_CACHE_6,
+    REG_DATA_CACHE_7,
+    REG_DATA_CACHE_8,
+    REG_DATA_CACHE_9,
+    REG_DATA_CACHE_A,
+    REG_DATA_CACHE_B,
+    REG_POWER_OUTPUT_CTRL = 0x12u,
+    REG_DC_DC2_OUT_V_CTRL = 0x23u,
+    REG_DC_DC2_DVS_CTRL = 0x25u,
+    REG_DC_DC3_OUT_V_CTRL = 0x27u,
+    REG_LDO2_4_OUT_V_CTRL,
+    REG_LDO3_OUT_V_CTRL,
+    REG_VBUS_CH_MGMT = 0x30u,
+    REG_SHUTDOWN_V_CTRL,
+    REG_SHUTDOWN_CTRL,
+    REG_CHARGE_CTRL_1,
+    REG_CHARGE_CTRL_2,
+    REG_SPARE_CHARGE_CTRL,
+    REG_PEK_KEY_CTRL,
+    REG_DC_DC_FREQ_SET,
+    REG_CHR_TEMP_TH_SET,
+    REG_CHR_HIGH_TEMP_TH_CTRL,
+    REG_IPSOUT_WARN_L1,
+    REG_IPSOUT_WARN_L2,
+    REG_DISCHR_TEMP_TH_SET,
+    REG_DISCHR_HIGH_TEMP_TH_CTRL,
+    REG_IRQ_BANK_1_CTRL = 0x40u,
+    REG_IRQ_BANK_2_CTRL,
+    REG_IRQ_BANK_3_CTRL,
+    REG_IRQ_BANK_4_CTRL,
+    REG_IRQ_BANK_5_CTRL,
+    REG_IRQ_BANK_1_STAT = 0x48u,
+    REG_IRQ_BANK_2_STAT,
+    REG_IRQ_BANK_3_STAT,
+    REG_IRQ_BANK_4_STAT,
+    REG_IRQ_BANK_5_STAT,
+    REG_ADC_ACIN_V_H = 0x56u,
+    REG_ADC_ACIN_V_L,
+    REG_ADC_ACIN_CURR_H,
+    REG_ADC_ACIN_CURR_L,
+    REG_ADC_VBUS_V_H,
+    REG_ADC_VBUS_V_L,
+    REG_ADC_VBUS_CURR_H,
+    REG_ADC_VBUS_CURR_L,
+    REG_ADC_INT_TEMP_H,
+    REG_ADC_INT_TEMP_L,
+    REG_ADC_TEMP_SENS_V_H = 0x62u,
+    REG_ADC_TEMP_SENS_V_L,
+    REG_ADC_BAT_V_H = 0x78u,
+    REG_ADC_BAT_V_L,
+    REG_ADC_BAT_DISCHR_CURR_H,
+    REG_ADC_BAT_DISCHR_CURR_L,
+    REG_ADC_BAT_CHR_CURR_H,
+    REG_ADC_BAT_CHR_CURR_L,
+    REG_ADC_IPSOUT_V_H,
+    REG_ADC_IPSOUT_V_L,
+    REG_DC_DC_MOD_SEL = 0x80u,
+    REG_ADC_EN_1,
+    REG_ADC_EN_2,
+    REG_ADC_SR_CTRL,
+    REG_ADC_IN_RANGE,
+    REG_GPIO1_ADC_IRQ_RISING_TH,
+    REG_GPIO1_ADC_IRQ_FALLING_TH,
+    REG_TIMER_CTRL = 0x8au,
+    REG_VBUS_CTRL_MON_SRP,
+    REG_OVER_TEMP_SHUTDOWN = 0x8fu,
+    REG_GPIO0_FEAT_SET,
+    REG_GPIO_OUT_HIGH_SET,
+    REG_GPIO1_FEAT_SET,
+    REG_GPIO2_FEAT_SET,
+    REG_GPIO_SIG_STATE_SET_MON,
+    REG_GPIO3_SET,
+    REG_COULOMB_CNTR_CTRL = 0xb8u,
+    REG_POWER_MEAS_RES,
+    NR_REGS
+};
+
+#define AXP_209_CHIP_VERSION_ID             (0x01)
+#define AXP_209_DC_DC2_OUT_V_CTRL_RESET     (0x16)
+#define AXP_209_IRQ_BANK_1_CTRL_RESET       (0xd8)
+
+/* A simple I2C slave which returns values of ID or CNT register. */
+typedef struct AXP209I2CState {
+    /*< private >*/
+    I2CSlave i2c;
+    /*< public >*/
+    uint8_t regs[NR_REGS];  /* peripheral registers */
+    uint8_t ptr;            /* current register index */
+    uint8_t count;          /* counter used for tx/rx */
+} AXP209I2CState;
+
+/* Reset all counters and load ID register */
+static void axp_209_reset_enter(Object *obj, ResetType type)
+{
+    AXP209I2CState *s = AXP_209(obj);
+
+    memset(s->regs, 0, NR_REGS);
+    s->ptr = 0;
+    s->count = 0;
+    s->regs[REG_CHIP_VERSION] = AXP_209_CHIP_VERSION_ID;
+    s->regs[REG_DC_DC2_OUT_V_CTRL] = AXP_209_DC_DC2_OUT_V_CTRL_RESET;
+    s->regs[REG_IRQ_BANK_1_CTRL] = AXP_209_IRQ_BANK_1_CTRL_RESET;
+}
+
+/* Handle events from master. */
+static int axp_209_event(I2CSlave *i2c, enum i2c_event event)
+{
+    AXP209I2CState *s = AXP_209(i2c);
+
+    s->count = 0;
+
+    return 0;
+}
+
+/* Called when master requests read */
+static uint8_t axp_209_rx(I2CSlave *i2c)
+{
+    AXP209I2CState *s = AXP_209(i2c);
+    uint8_t ret = 0xff;
+
+    if (s->ptr < NR_REGS) {
+        ret = s->regs[s->ptr++];
+    }
+
+    trace_allwinner_axp_209_rx(s->ptr - 1, ret);
+
+    return ret;
+}
+
+/*
+ * Called when master sends write.
+ * Update ptr with byte 0, then perform write with second byte.
+ */
+static int axp_209_tx(I2CSlave *i2c, uint8_t data)
+{
+    AXP209I2CState *s = AXP_209(i2c);
+
+    if (s->count == 0) {
+        /* Store register address */
+        s->ptr = data;
+        s->count++;
+        trace_allwinner_axp_209_select(data);
+    } else {
+        trace_allwinner_axp_209_tx(s->ptr, data);
+        if (s->ptr == REG_DC_DC2_OUT_V_CTRL) {
+            s->regs[s->ptr++] = data;
+        }
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_axp_209 = {
+    .name = TYPE_AXP_209,
+    .version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8_ARRAY(regs, AXP209I2CState, NR_REGS),
+        VMSTATE_UINT8(count, AXP209I2CState),
+        VMSTATE_UINT8(ptr, AXP209I2CState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void axp_209_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc);
+    ResettableClass *rc = RESETTABLE_CLASS(oc);
+
+    rc->phases.enter = axp_209_reset_enter;
+    dc->vmsd = &vmstate_axp_209;
+    isc->event = axp_209_event;
+    isc->recv = axp_209_rx;
+    isc->send = axp_209_tx;
+}
+
+static const TypeInfo axp_209_info = {
+    .name = TYPE_AXP_209,
+    .parent = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(AXP209I2CState),
+    .class_init = axp_209_class_init
+};
+
+static void axp_209_register_devices(void)
+{
+    type_register_static(&axp_209_info);
+}
+
+type_init(axp_209_register_devices);
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 9eaa0750b5..7d332851cb 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -40,6 +40,7 @@  softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
 
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_DRAMC', if_true: files('allwinner-a10-dramc.c'))
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_AXP_209', if_true: files('allwinner-axp-209.c'))
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
 specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'))
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index c18bc0605e..f6a7a6901f 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -1,5 +1,10 @@ 
 # See docs/devel/tracing.rst for syntax documentation.
 
+# allwinner-axp209.c
+allwinner_axp_209_rx(uint8_t reg, uint8_t data) "Read reg 0x%" PRIx8 " : 0x%" PRIx8
+allwinner_axp_209_select(uint8_t reg) "Accessing reg 0x%" PRIx8
+allwinner_axp_209_tx(uint8_t reg, uint8_t data) "Write reg 0x%" PRIx8 " : 0x%" PRIx8
+
 # allwinner-cpucfg.c
 allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_addr 0x%" PRIx32
 allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32