> Date: Wed, 15 Sep 2021 17:29:39 +0200 (CEST)
> From: Mark Kettenis <mark.kette...@xs4all.nl>
> 
> The diff below is a preliminary diff to fix a suspend/resume issue on
> recent Thinkpads.  This needs testing on a wider range of laptops to
> make sure it doesn't break things.  The diff also puts some
> information in dmesg that will help me improve things in the future.
> 
> So, if you have a laptop where pchgpio(4) attaches *and* supports S3
> suspen/resume, please apply this diff, do a suspend/resume cycle and
> send me a dmesg collected after that suspend/resume cycle.

This diff is now in snapshots, so instead of applying the diff and
build your own kernel, you can just upgrade to the latest snapshot.

Thanks,

Mark

> Index: dev/acpi/pchgpio.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/acpi/pchgpio.c,v
> retrieving revision 1.5
> diff -u -p -r1.5 pchgpio.c
> --- dev/acpi/pchgpio.c        30 Aug 2021 18:40:19 -0000      1.5
> +++ dev/acpi/pchgpio.c        15 Sep 2021 15:16:52 -0000
> @@ -28,12 +28,13 @@
>  
>  #define PCHGPIO_MAXCOM               4
>  
> -#define PCHGPIO_CONF_TXSTATE 0x00000001
> -#define PCHGPIO_CONF_RXSTATE 0x00000002
> -#define PCHGPIO_CONF_RXINV   0x00800000
> -#define PCHGPIO_CONF_RXEV_EDGE       0x02000000
> -#define PCHGPIO_CONF_RXEV_ZERO       0x04000000
> -#define PCHGPIO_CONF_RXEV_MASK       0x06000000
> +#define PCHGPIO_CONF_TXSTATE         0x00000001
> +#define PCHGPIO_CONF_RXSTATE         0x00000002
> +#define PCHGPIO_CONF_RXINV           0x00800000
> +#define PCHGPIO_CONF_RXEV_EDGE               0x02000000
> +#define PCHGPIO_CONF_RXEV_ZERO               0x04000000
> +#define PCHGPIO_CONF_RXEV_MASK               0x06000000
> +#define PCHGPIO_CONF_PADRSTCFG_MASK  0xc0000000
>  
>  #define PCHGPIO_PADBAR               0x00c
>  
> @@ -59,6 +60,11 @@ struct pchgpio_match {
>       const struct pchgpio_device *device;
>  };
>  
> +struct pchgpio_pincfg {
> +     uint32_t        pad_cfg_dw0;
> +     uint32_t        pad_cfg_dw1;
> +};
> +
>  struct pchgpio_intrhand {
>       int (*ih_func)(void *);
>       void *ih_arg;
> @@ -80,6 +86,7 @@ struct pchgpio_softc {
>       int sc_padsize;
>  
>       int sc_npins;
> +     struct pchgpio_pincfg *sc_pin_cfg;
>       struct pchgpio_intrhand *sc_pin_ih;
>  
>       struct acpi_gpio sc_gpio;
> @@ -87,9 +94,11 @@ struct pchgpio_softc {
>  
>  int  pchgpio_match(struct device *, void *, void *);
>  void pchgpio_attach(struct device *, struct device *, void *);
> +int  pchgpio_activate(struct device *, int);
>  
>  struct cfattach pchgpio_ca = {
> -     sizeof(struct pchgpio_softc), pchgpio_match, pchgpio_attach
> +     sizeof(struct pchgpio_softc), pchgpio_match, pchgpio_attach,
> +     NULL, pchgpio_activate
>  };
>  
>  struct cfdriver pchgpio_cd = {
> @@ -170,6 +179,8 @@ int       pchgpio_read_pin(void *, int);
>  void pchgpio_write_pin(void *, int, int);
>  void pchgpio_intr_establish(void *, int, int, int (*)(void *), void *);
>  int  pchgpio_intr(void *);
> +void pchgpio_save(struct pchgpio_softc *);
> +void pchgpio_restore(struct pchgpio_softc *);
>  
>  int
>  pchgpio_match(struct device *parent, void *match, void *aux)
> @@ -240,6 +251,8 @@ pchgpio_attach(struct device *parent, st
>  
>       sc->sc_padsize = sc->sc_device->pad_size;
>       sc->sc_npins = sc->sc_device->npins;
> +     sc->sc_pin_cfg = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_cfg),
> +         M_DEVBUF, M_WAITOK);
>       sc->sc_pin_ih = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_ih),
>           M_DEVBUF, M_WAITOK | M_ZERO);
>  
> @@ -263,11 +276,48 @@ pchgpio_attach(struct device *parent, st
>  
>  unmap:
>       free(sc->sc_pin_ih, M_DEVBUF, sc->sc_npins * sizeof(*sc->sc_pin_ih));
> +     free(sc->sc_pin_cfg, M_DEVBUF, sc->sc_npins * sizeof(*sc->sc_pin_cfg));
>       for (i = 0; i < sc->sc_naddr; i++)
>               bus_space_unmap(sc->sc_memt[i], sc->sc_memh[i],
>                   aaa->aaa_size[i]);
>  }
>  
> +int
> +pchgpio_activate(struct device *self, int act)
> +{
> +     struct pchgpio_softc *sc = (struct pchgpio_softc *)self;
> +//   int i, j;
> +
> +     switch (act) {
> +     case DVACT_SUSPEND:
> +             printf("%s: suspend\n", sc->sc_dev.dv_xname);
> +#if 0
> +             for (i = 0; i < 4; i++) {
> +                     for (j = 0; j < 0xc00; j += 4) {
> +                             printf("%04x: 0x%08x\n", j,
> +                                 bus_space_read_4(sc->sc_memt[i], 
> sc->sc_memh[i], j));
> +                     }
> +             }
> +#endif
> +             pchgpio_save(sc);
> +             break;
> +     case DVACT_RESUME:
> +             printf("%s: resume\n", sc->sc_dev.dv_xname);
> +#if 0
> +             for (i = 0; i < 4; i++) {
> +                     for (j = 0; j < 0xc00; j += 4) {
> +                             printf("%04x: 0x%08x\n", j,
> +                                 bus_space_read_4(sc->sc_memt[i], 
> sc->sc_memh[i], j));
> +                     }
> +             }
> +#endif
> +             pchgpio_restore(sc);
> +             break;
> +     }
> +
> +     return 0;
> +}
> +
>  const struct pchgpio_group *
>  pchgpio_find_group(struct pchgpio_softc *sc, int pin)
>  {
> @@ -403,4 +453,74 @@ pchgpio_intr(void *arg)
>       }
>  
>       return handled;
> +}
> +
> +void
> +pchgpio_save(struct pchgpio_softc *sc)
> +{
> +     int gpiobase, group, bit, pin, pad;
> +     uint16_t base, limit;
> +     uint8_t bank, bar;
> +
> +     for (group = 0; group < sc->sc_device->ngroups; group++) {
> +             bar = sc->sc_device->groups[group].bar;
> +             bank = sc->sc_device->groups[group].bank;
> +             base = sc->sc_device->groups[group].base;
> +             limit = sc->sc_device->groups[group].limit;
> +             gpiobase = sc->sc_device->groups[group].gpiobase;
> +
> +             for (bit = 0; bit <= (limit - base); bit++) {
> +                     pin = gpiobase + bit;
> +                     pad = base + bit - sc->sc_padbase[bar];
> +
> +                     sc->sc_pin_cfg[pin].pad_cfg_dw0 =
> +                         bus_space_read_4(sc->sc_memt[bar],
> +                             sc->sc_memh[bar],
> +                             sc->sc_padbar[bar] + pad * sc->sc_padsize);
> +                     sc->sc_pin_cfg[pin].pad_cfg_dw1 =
> +                         bus_space_read_4(sc->sc_memt[bar],
> +                             sc->sc_memh[bar],
> +                             sc->sc_padbar[bar] + pad * sc->sc_padsize + 4);
> +             }
> +     }
> +}
> +
> +void
> +pchgpio_restore(struct pchgpio_softc *sc)
> +{
> +     int gpiobase, group, bit, pin, pad;
> +     uint32_t pad_cfg_dw0, pad_cfg_dw1;
> +     uint16_t base, limit;
> +     uint8_t bank, bar;
> +
> +     for (group = 0; group < sc->sc_device->ngroups; group++) {
> +             bar = sc->sc_device->groups[group].bar;
> +             bank = sc->sc_device->groups[group].bank;
> +             base = sc->sc_device->groups[group].base;
> +             limit = sc->sc_device->groups[group].limit;
> +             gpiobase = sc->sc_device->groups[group].gpiobase;
> +
> +             for (bit = 0; bit <= (limit - base); bit++) {
> +                     pin = gpiobase + bit;
> +                     pad = base + bit - sc->sc_padbase[bar];
> +
> +                     pad_cfg_dw0 = bus_space_read_4(sc->sc_memt[bar],
> +                         sc->sc_memh[bar], sc->sc_padbar[bar] + pad * 
> sc->sc_padsize);
> +                     pad_cfg_dw1 = bus_space_read_4(sc->sc_memt[bar],
> +                         sc->sc_memh[bar], sc->sc_padbar[bar] + pad * 
> sc->sc_padsize + 4);
> +                     if (pad_cfg_dw0 != sc->sc_pin_cfg[pin].pad_cfg_dw0)
> +                             printf("bar %d bank %d bit %d pad %d: dw0 
> 0x%08x -> 0x%08x\n", bar, bank, bit, pad, sc->sc_pin_cfg[pin].pad_cfg_dw0, 
> pad_cfg_dw0);
> +                     if (pad_cfg_dw1 != sc->sc_pin_cfg[pin].pad_cfg_dw1)
> +                             printf("bar %d bank %d bit %d pad %d: dw1 
> 0x%08x -> 0x%08x\n", bar, bank, bit, pad, sc->sc_pin_cfg[pin].pad_cfg_dw1, 
> pad_cfg_dw1);
> +
> +                     /* XXX */
> +                     if ((sc->sc_pin_cfg[pin].pad_cfg_dw0 & 
> PCHGPIO_CONF_PADRSTCFG_MASK) !=
> +                         (pad_cfg_dw0 & PCHGPIO_CONF_PADRSTCFG_MASK)) {
> +                             bus_space_write_4(sc->sc_memt[bar],
> +                                 sc->sc_memh[bar],
> +                                 sc->sc_padbar[bar] + pad * sc->sc_padsize,
> +                                 sc->sc_pin_cfg[pin].pad_cfg_dw0);
> +                     }
> +             }
> +     }
>  }
> 
> 

Reply via email to