| 99 | } |
| 100 | |
| 101 | int |
| 102 | pmu_attach(device_t dev) |
| 103 | { |
| 104 | struct pmu_softc *sc; |
| 105 | #if defined(__arm__) && (__ARM_ARCH > 6) |
| 106 | uint32_t iesr; |
| 107 | #endif |
| 108 | int err, i; |
| 109 | |
| 110 | sc = device_get_softc(dev); |
| 111 | sc->dev = dev; |
| 112 | |
| 113 | for (i = 0; i < MAX_RLEN; i++) { |
| 114 | if (sc->irq[i].res == NULL) |
| 115 | break; |
| 116 | err = bus_setup_intr(dev, sc->irq[i].res, |
| 117 | INTR_MPSAFE | INTR_TYPE_MISC, pmu_intr, NULL, NULL, |
| 118 | &sc->irq[i].ih); |
| 119 | if (err != 0) { |
| 120 | device_printf(dev, |
| 121 | "Unable to setup interrupt handler.\n"); |
| 122 | goto fail; |
| 123 | } |
| 124 | if (sc->irq[i].cpuid != -1) { |
| 125 | err = bus_bind_intr(dev, sc->irq[i].res, |
| 126 | sc->irq[i].cpuid); |
| 127 | if (err != 0) { |
| 128 | device_printf(sc->dev, |
| 129 | "Unable to bind interrupt.\n"); |
| 130 | goto fail; |
| 131 | } |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | #if defined(__arm__) && (__ARM_ARCH > 6) |
| 136 | /* Initialize to 0. */ |
| 137 | for (i = 0; i < MAXCPU; i++) |
| 138 | ccnt_hi[i] = 0; |
| 139 | |
| 140 | /* Enable the interrupt to fire on overflow. */ |
| 141 | iesr = cp15_pminten_get(); |
| 142 | iesr |= PMU_IESR_C; |
| 143 | cp15_pminten_set(iesr); |
| 144 | |
| 145 | /* Need this for getcyclecount() fast path. */ |
| 146 | pmu_attched |= 1; |
| 147 | #endif |
| 148 | |
| 149 | return (0); |
| 150 | |
| 151 | fail: |
| 152 | for (i = 1; i < MAX_RLEN; i++) { |
| 153 | if (sc->irq[i].ih != NULL) |
| 154 | bus_teardown_intr(dev, sc->irq[i].res, sc->irq[i].ih); |
| 155 | if (sc->irq[i].res != NULL) |
| 156 | bus_release_resource(dev, SYS_RES_IRQ, i, |
| 157 | sc->irq[i].res); |
| 158 | } |
no test coverage detected