[BACK]Return to ihidev.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / i2c

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/dev/i2c/ihidev.c between version 1.20 and 1.21

version 1.20, 2021/08/07 16:19:11 version 1.21, 2022/01/14 22:25:49
Line 60  __KERNEL_RCSID(0, "$NetBSD$");
Line 60  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/device.h>  #include <sys/device.h>
 #include <sys/kmem.h>  #include <sys/kmem.h>
   #include <sys/workqueue.h>
   
 #include <dev/i2c/i2cvar.h>  #include <dev/i2c/i2cvar.h>
 #include <dev/i2c/ihidev.h>  #include <dev/i2c/ihidev.h>
Line 110  static int ihidev_detach(device_t, int);
Line 110  static int ihidev_detach(device_t, int);
 CFATTACH_DECL_NEW(ihidev, sizeof(struct ihidev_softc),  CFATTACH_DECL_NEW(ihidev, sizeof(struct ihidev_softc),
     ihidev_match, ihidev_attach, ihidev_detach, NULL);      ihidev_match, ihidev_attach, ihidev_detach, NULL);
   
 static bool     ihiddev_intr_init(struct ihidev_softc *);  static bool     ihidev_intr_init(struct ihidev_softc *);
 static void     ihiddev_intr_fini(struct ihidev_softc *);  static void     ihidev_intr_fini(struct ihidev_softc *);
   
 static bool     ihidev_suspend(device_t, const pmf_qual_t *);  static bool     ihidev_suspend(device_t, const pmf_qual_t *);
 static bool     ihidev_resume(device_t, const pmf_qual_t *);  static bool     ihidev_resume(device_t, const pmf_qual_t *);
 static int      ihidev_hid_command(struct ihidev_softc *, int, void *, bool);  static int      ihidev_hid_command(struct ihidev_softc *, int, void *, bool);
 static int      ihidev_intr(void *);  static int      ihidev_intr(void *);
 static void     ihidev_softintr(void *);  static void     ihidev_work(struct work *, void *);
 static int      ihidev_reset(struct ihidev_softc *, bool);  static int      ihidev_reset(struct ihidev_softc *, bool);
 static int      ihidev_hid_desc_parse(struct ihidev_softc *);  static int      ihidev_hid_desc_parse(struct ihidev_softc *);
   
Line 160  ihidev_attach(device_t parent, device_t 
Line 160  ihidev_attach(device_t parent, device_t 
         sc->sc_dev = self;          sc->sc_dev = self;
         sc->sc_tag = ia->ia_tag;          sc->sc_tag = ia->ia_tag;
         sc->sc_addr = ia->ia_addr;          sc->sc_addr = ia->ia_addr;
         mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_VM);          mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
   
         sc->sc_phandle = ia->ia_cookie;          sc->sc_phandle = ia->ia_cookie;
         if (ia->ia_cookietype != I2C_COOKIE_ACPI) {          if (ia->ia_cookietype != I2C_COOKIE_ACPI) {
                 aprint_error(": unsupported device tree type\n");                  aprint_error(": unsupported device tree type\n");
                 return;                  return;
         }          }
         if (! ihidev_acpi_get_info(sc)) {          if (!ihidev_acpi_get_info(sc)) {
                 return;                  return;
         }          }
   
Line 208  ihidev_attach(device_t parent, device_t 
Line 208  ihidev_attach(device_t parent, device_t 
                     repsz));                      repsz));
         }          }
         sc->sc_ibuf = kmem_zalloc(sc->sc_isize, KM_SLEEP);          sc->sc_ibuf = kmem_zalloc(sc->sc_isize, KM_SLEEP);
         if (! ihiddev_intr_init(sc)) {          if (!ihidev_intr_init(sc)) {
                 return;                  return;
         }          }
   
Line 245  ihidev_attach(device_t parent, device_t 
Line 245  ihidev_attach(device_t parent, device_t 
         }          }
   
         /* power down until we're opened */          /* power down until we're opened */
         if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, &I2C_HID_POWER_OFF, false)) {          if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, &I2C_HID_POWER_OFF,
                   false)) {
                 aprint_error_dev(sc->sc_dev, "failed to power down\n");                  aprint_error_dev(sc->sc_dev, "failed to power down\n");
                 return;                  return;
         }          }
Line 257  static int
Line 258  static int
 ihidev_detach(device_t self, int flags)  ihidev_detach(device_t self, int flags)
 {  {
         struct ihidev_softc *sc = device_private(self);          struct ihidev_softc *sc = device_private(self);
           int error;
   
           error = config_detach_children(self, flags);
           if (error)
                   return error;
   
           pmf_device_deregister(self);
           ihidev_intr_fini(sc);
   
           if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, &I2C_HID_POWER_OFF,
                   true))
                   aprint_error_dev(sc->sc_dev, "failed to power down\n");
   
         mutex_enter(&sc->sc_intr_lock);  
         ihiddev_intr_fini(sc);  
         if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER,  
             &I2C_HID_POWER_OFF, true))  
         aprint_error_dev(sc->sc_dev, "failed to power down\n");  
         mutex_exit(&sc->sc_intr_lock);  
         if (sc->sc_ibuf != NULL) {          if (sc->sc_ibuf != NULL) {
                 kmem_free(sc->sc_ibuf, sc->sc_isize);                  kmem_free(sc->sc_ibuf, sc->sc_isize);
                 sc->sc_ibuf = NULL;                  sc->sc_ibuf = NULL;
Line 272  ihidev_detach(device_t self, int flags)
Line 279  ihidev_detach(device_t self, int flags)
         if (sc->sc_report != NULL)          if (sc->sc_report != NULL)
                 kmem_free(sc->sc_report, sc->sc_reportlen);                  kmem_free(sc->sc_report, sc->sc_reportlen);
   
         pmf_device_deregister(self);          mutex_destroy(&sc->sc_lock);
         return (0);  
           return 0;
 }  }
   
 static bool  static bool
Line 281  ihidev_suspend(device_t self, const pmf_
Line 289  ihidev_suspend(device_t self, const pmf_
 {  {
         struct ihidev_softc *sc = device_private(self);          struct ihidev_softc *sc = device_private(self);
   
         mutex_enter(&sc->sc_intr_lock);          mutex_enter(&sc->sc_lock);
         if (sc->sc_refcnt > 0) {          if (sc->sc_refcnt > 0) {
                 printf("ihidev power off\n");                  printf("ihidev power off\n");
                 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER,                  if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER,
                     &I2C_HID_POWER_OFF, true))                      &I2C_HID_POWER_OFF, true))
                 aprint_error_dev(sc->sc_dev, "failed to power down\n");                  aprint_error_dev(sc->sc_dev, "failed to power down\n");
         }          }
         mutex_exit(&sc->sc_intr_lock);          mutex_exit(&sc->sc_lock);
         return true;          return true;
 }  }
   
Line 297  ihidev_resume(device_t self, const pmf_q
Line 305  ihidev_resume(device_t self, const pmf_q
 {  {
         struct ihidev_softc *sc = device_private(self);          struct ihidev_softc *sc = device_private(self);
   
         mutex_enter(&sc->sc_intr_lock);          mutex_enter(&sc->sc_lock);
         if (sc->sc_refcnt > 0) {          if (sc->sc_refcnt > 0) {
                 printf("ihidev power reset\n");                  printf("ihidev power reset\n");
                 ihidev_reset(sc, true);                  ihidev_reset(sc, true);
         }          }
         mutex_exit(&sc->sc_intr_lock);          mutex_exit(&sc->sc_lock);
         return true;          return true;
 }  }
   
Line 646  ihidev_hid_desc_parse(struct ihidev_soft
Line 654  ihidev_hid_desc_parse(struct ihidev_soft
 }  }
   
 static bool  static bool
 ihiddev_intr_init(struct ihidev_softc *sc)  ihidev_intr_init(struct ihidev_softc *sc)
 {  {
 #if NACPICA > 0  #if NACPICA > 0
         ACPI_HANDLE hdl = (void *)(uintptr_t)sc->sc_phandle;          ACPI_HANDLE hdl = (void *)(uintptr_t)sc->sc_phandle;
Line 682  ihiddev_intr_init(struct ihidev_softc *s
Line 690  ihiddev_intr_init(struct ihidev_softc *s
         aprint_normal_dev(sc->sc_dev, "interrupting at %s\n",          aprint_normal_dev(sc->sc_dev, "interrupting at %s\n",
             acpi_intr_string(sc->sc_ih, buf, sizeof(buf)));              acpi_intr_string(sc->sc_ih, buf, sizeof(buf)));
   
         sc->sc_sih = softint_establish(SOFTINT_SERIAL, ihidev_softintr, sc);          if (workqueue_create(&sc->sc_wq, device_xname(sc->sc_dev), ihidev_work,
         if (sc->sc_sih == NULL) {                  sc, PRI_NONE, IPL_TTY, WQ_MPSAFE)) {
                 aprint_error_dev(sc->sc_dev,                  aprint_error_dev(sc->sc_dev,
                     "can't establish soft interrupt\n");                      "can't establish workqueue\n");
                 return false;                  return false;
         }          }
           sc->sc_work_pending = 0;
   
         return true;          return true;
 #else  #else
Line 697  ihiddev_intr_init(struct ihidev_softc *s
Line 706  ihiddev_intr_init(struct ihidev_softc *s
 }  }
   
 static void  static void
 ihiddev_intr_fini(struct ihidev_softc *sc)  ihidev_intr_fini(struct ihidev_softc *sc)
 {  {
 #if NACPICA > 0  #if NACPICA > 0
         if (sc->sc_ih != NULL) {          if (sc->sc_ih != NULL) {
                 acpi_intr_disestablish(sc->sc_ih);                  acpi_intr_disestablish(sc->sc_ih);
         }          }
         if (sc->sc_sih != NULL) {          if (sc->sc_wq != NULL) {
                 softint_disestablish(sc->sc_sih);                  workqueue_destroy(sc->sc_wq);
         }          }
 #endif  #endif
 }  }
Line 736  ihidev_intr(void *arg)
Line 745  ihidev_intr(void *arg)
 {  {
         struct ihidev_softc * const sc = arg;          struct ihidev_softc * const sc = arg;
   
         mutex_enter(&sc->sc_intr_lock);  
   
         /*          /*
          * Schedule our soft interrupt handler.  If we're using a level-           * Schedule our work.  If we're using a level-triggered
          * triggered interrupt, we have to mask it off while we wait           * interrupt, we have to mask it off while we wait for service.
          * for service.  
          */           */
         softint_schedule(sc->sc_sih);          if (atomic_swap_uint(&sc->sc_work_pending, 1) == 0)
                   workqueue_enqueue(sc->sc_wq, &sc->sc_work, NULL);
         ihidev_intr_mask(sc);          ihidev_intr_mask(sc);
   
         mutex_exit(&sc->sc_intr_lock);  
   
         return 1;          return 1;
 }  }
   
 static void  static void
 ihidev_softintr(void *arg)  ihidev_work(struct work *wk, void *arg)
 {  {
         struct ihidev_softc * const sc = arg;          struct ihidev_softc * const sc = arg;
         struct ihidev *scd;          struct ihidev *scd;
Line 761  ihidev_softintr(void *arg)
Line 766  ihidev_softintr(void *arg)
         u_char *p;          u_char *p;
         u_int rep = 0;          u_int rep = 0;
   
         mutex_enter(&sc->sc_intr_lock);          atomic_store_relaxed(&sc->sc_work_pending, 0);
   
           mutex_enter(&sc->sc_lock);
   
         iic_acquire_bus(sc->sc_tag, 0);          iic_acquire_bus(sc->sc_tag, 0);
         res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, NULL, 0,          res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, NULL, 0,
             sc->sc_ibuf, sc->sc_isize, 0);              sc->sc_ibuf, sc->sc_isize, 0);
         iic_release_bus(sc->sc_tag, 0);          iic_release_bus(sc->sc_tag, 0);
         mutex_exit(&sc->sc_intr_lock);  
   
         if (res != 0)          if (res != 0)
                 goto out;                  goto out;
   
Line 807  ihidev_softintr(void *arg)
Line 813  ihidev_softintr(void *arg)
         scd->sc_intr(scd, p, psize);          scd->sc_intr(scd, p, psize);
   
  out:   out:
           mutex_exit(&sc->sc_lock);
   
         /*          /*
          * If our interrupt is level-triggered, re-enable it now.           * If our interrupt is level-triggered, re-enable it now.
          */           */
Line 837  ihidev_print(void *aux, const char *pnp)
Line 845  ihidev_print(void *aux, const char *pnp)
   
         if (iha->reportid == IHIDEV_CLAIM_ALLREPORTID)          if (iha->reportid == IHIDEV_CLAIM_ALLREPORTID)
                 return (QUIET);                  return (QUIET);
   
         if (pnp)          if (pnp)
                 aprint_normal("hid at %s", pnp);                  aprint_normal("hid at %s", pnp);
   
Line 974  ihidev_set_report(struct device *dev, in
Line 982  ihidev_set_report(struct device *dev, in
   
 static bool  static bool
 ihidev_acpi_get_info(struct ihidev_softc *sc)  ihidev_acpi_get_info(struct ihidev_softc *sc)
 {  {
         ACPI_HANDLE hdl = (void *)(uintptr_t)sc->sc_phandle;          ACPI_HANDLE hdl = (void *)(uintptr_t)sc->sc_phandle;
         ACPI_STATUS status;          ACPI_STATUS status;
         ACPI_INTEGER val;          ACPI_INTEGER val;

Legend:
Removed from v.1.20  
changed lines
  Added in v.1.21

CVSweb <webmaster@jp.NetBSD.org>