qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Miles Glenn <milesg@linux.vnet.ibm.com>
To: "Cédric Le Goater" <clg@kaod.org>, qemu-devel@nongnu.org
Cc: qemu-arm@nongnu.org, andrew@codeconstruct.com.au,
	Joel Stanley <joel@jms.id.au>
Subject: Re: [PATCH v2] misc/pca9552: Let external devices set pca9552 inputs
Date: Wed, 11 Oct 2023 14:16:16 -0500	[thread overview]
Message-ID: <37b0967012f909184d6965bc80d617d59cd49dd5.camel@linux.vnet.ibm.com> (raw)
In-Reply-To: <08fe62cf-7301-6f44-4239-2dd76a2436cf@kaod.org>

On Wed, 2023-10-11 at 19:05 +0200, Cédric Le Goater wrote:
> On 10/5/23 22:41, Glenn Miles wrote:
> > Allow external devices to drive pca9552 input pins by adding
> > input GPIO's to the model.  This allows a device to connect
> > its output GPIO's to the pca9552 input GPIO's.
> > 
> > In order for an external device to set the state of a pca9552
> > pin, the pin must first be configured for high impedance (LED
> > is off).  If the pca9552 pin is configured to drive the pin low
> > (LED is on), then external input will be ignored.
> > 
> > Signed-off-by: Glenn Miles <milesg@linux.vnet.ibm.com>
> 
> Why an extra ext_state array ? The input handler should simply update
> the PCA9552_INPUT* registers if the PCA9552_LS* register is
> programmed
> in input mode ?
> 

The ext_state array is needed because the PCA9552_INPUT* values are
now determined by two inputs:  1) The ouput state of the pca9552
device (high impedance or low) and 2) The input from an external
device (also high impedance or low).  Either of these inputs could
change independently of each other, so we can't assume that just
because the pca9552 is driving the gpio low that any external
device is also driving the gpio low.  When the pca9552 switches
its output to high impedance, we must look at how the exernal device
is currently driving the gpio before we can know the new value of the
pin.

> It would be nice to add some test case also.

Yes, I agree.  I have a crude test case that I'm using for my own
testing, but I think it has dependencies on other code (not mine) that
has not been upstreamed yet.  I will look into this.

Thanks,

Glenn

> 
> Thanks,
> 
> C.
> 
> 
> 
> > ---
> > Based-on: <20230927203221.3286895-1-milesg@linux.vnet.ibm.com>
> > ([PATCH] misc/pca9552: Fix inverted input status)
> >   hw/misc/pca9552.c         | 39
> > ++++++++++++++++++++++++++++++++++-----
> >   include/hw/misc/pca9552.h |  3 ++-
> >   2 files changed, 36 insertions(+), 6 deletions(-)
> > 
> > diff --git a/hw/misc/pca9552.c b/hw/misc/pca9552.c
> > index ad811fb249..f28b5ecd7e 100644
> > --- a/hw/misc/pca9552.c
> > +++ b/hw/misc/pca9552.c
> > @@ -113,16 +113,22 @@ static void
> > pca955x_update_pin_input(PCA955xState *s)
> >           switch (config) {
> >           case PCA9552_LED_ON:
> >               /* Pin is set to 0V to turn on LED */
> > -            qemu_set_irq(s->gpio[i], 0);
> > +            qemu_set_irq(s->gpio_out[i], 0);
> >               s->regs[input_reg] &= ~(1 << input_shift);
> >               break;
> >           case PCA9552_LED_OFF:
> >               /*
> >                * Pin is set to Hi-Z to turn off LED and
> > -             * pullup sets it to a logical 1.
> > +             * pullup sets it to a logical 1 unless
> > +             * external device drives it low.
> >                */
> > -            qemu_set_irq(s->gpio[i], 1);
> > -            s->regs[input_reg] |= 1 << input_shift;
> > +            if (s->ext_state[i] == 0) {
> > +                qemu_set_irq(s->gpio_out[i], 0);
> > +                s->regs[input_reg] &= ~(1 << input_shift);
> > +            } else {
> > +                qemu_set_irq(s->gpio_out[i], 1);
> > +                s->regs[input_reg] |= 1 << input_shift;
> > +            }
> >               break;
> >           case PCA9552_LED_PWM0:
> >           case PCA9552_LED_PWM1:
> > @@ -337,6 +343,7 @@ static const VMStateDescription pca9552_vmstate
> > = {
> >           VMSTATE_UINT8(len, PCA955xState),
> >           VMSTATE_UINT8(pointer, PCA955xState),
> >           VMSTATE_UINT8_ARRAY(regs, PCA955xState, PCA955X_NR_REGS),
> > +        VMSTATE_UINT8_ARRAY(ext_state, PCA955xState,
> > PCA955X_PIN_COUNT_MAX),
> >           VMSTATE_I2C_SLAVE(i2c, PCA955xState),
> >           VMSTATE_END_OF_LIST()
> >       }
> > @@ -355,6 +362,7 @@ static void pca9552_reset(DeviceState *dev)
> >       s->regs[PCA9552_LS2] = 0x55;
> >       s->regs[PCA9552_LS3] = 0x55;
> >   
> > +    memset(s->ext_state, 1, PCA955X_PIN_COUNT_MAX);
> >       pca955x_update_pin_input(s);
> >   
> >       s->pointer = 0xFF;
> > @@ -377,6 +385,26 @@ static void pca955x_initfn(Object *obj)
> >       }
> >   }
> >   
> > +static void pca955x_set_ext_state(PCA955xState *s, int pin, int
> > level)
> > +{
> > +    if (s->ext_state[pin] != level) {
> > +        uint16_t pins_status = pca955x_pins_get_status(s);
> > +        s->ext_state[pin] = level;
> > +        pca955x_update_pin_input(s);
> > +        pca955x_display_pins_status(s, pins_status);
> > +    }
> > +}
> > +
> > +static void pca955x_gpio_in_handler(void *opaque, int pin, int
> > level)
> > +{
> > +
> > +    PCA955xState *s = PCA955X(opaque);
> > +    PCA955xClass *k = PCA955X_GET_CLASS(s);
> > +
> > +    assert((pin >= 0) && (pin < k->pin_count));
> > +    pca955x_set_ext_state(s, pin, level);
> > +}
> > +
> >   static void pca955x_realize(DeviceState *dev, Error **errp)
> >   {
> >       PCA955xClass *k = PCA955X_GET_CLASS(dev);
> > @@ -386,7 +414,8 @@ static void pca955x_realize(DeviceState *dev,
> > Error **errp)
> >           s->description = g_strdup("pca-unspecified");
> >       }
> >   
> > -    qdev_init_gpio_out(dev, s->gpio, k->pin_count);
> > +    qdev_init_gpio_out(dev, s->gpio_out, k->pin_count);
> > +    qdev_init_gpio_in(dev, pca955x_gpio_in_handler, k->pin_count);
> >   }
> >   
> >   static Property pca955x_properties[] = {
> > diff --git a/include/hw/misc/pca9552.h b/include/hw/misc/pca9552.h
> > index b6f4e264fe..c36525f0c3 100644
> > --- a/include/hw/misc/pca9552.h
> > +++ b/include/hw/misc/pca9552.h
> > @@ -30,7 +30,8 @@ struct PCA955xState {
> >       uint8_t pointer;
> >   
> >       uint8_t regs[PCA955X_NR_REGS];
> > -    qemu_irq gpio[PCA955X_PIN_COUNT_MAX];
> > +    qemu_irq gpio_out[PCA955X_PIN_COUNT_MAX];
> > +    uint8_t ext_state[PCA955X_PIN_COUNT_MAX];
> >       char *description; /* For debugging purpose only */
> >   };
> >   



      reply	other threads:[~2023-10-11 19:22 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-05 20:41 [PATCH v2] misc/pca9552: Let external devices set pca9552 inputs Glenn Miles
2023-10-10 12:32 ` Joel Stanley
2023-10-12 22:40   ` Miles Glenn
2023-10-11 17:05 ` Cédric Le Goater
2023-10-11 19:16   ` Miles Glenn [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=37b0967012f909184d6965bc80d617d59cd49dd5.camel@linux.vnet.ibm.com \
    --to=milesg@linux.vnet.ibm.com \
    --cc=andrew@codeconstruct.com.au \
    --cc=clg@kaod.org \
    --cc=joel@jms.id.au \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).