+/* calculate best 8bit prescaler and divisor for given usec timeout */
+static int best_prescaler(u_int64_t timeout, u_int8_t *prescaler,
+ u_int8_t *divisor)
+{
+ u_int8_t best_prescaler, best_divisor, i;
+ int64_t smallest_diff;
+
+ smallest_diff = LLONG_MAX;
+ best_prescaler = 0;
+
+ for (i = 0; i < 21; i++) {
+ u_int64_t clk, tmp_div, res;
+ int64_t diff;
+ clk = 13560000 / (1 << i);
+ tmp_div = (clk * timeout) / 1000000;
+ tmp_div++;
+
+ if ((tmp_div > 0xff) || (tmp_div > clk))
+ continue;
+
+ res = 1000000 / (clk / tmp_div);
+ diff = res - timeout;
+
+ if (diff < 0)
+ continue;
+
+ if (diff < smallest_diff) {
+ best_prescaler = i;
+ best_divisor = tmp_div;
+ smallest_diff = diff;
+ }
+ }
+
+ *prescaler = best_prescaler;
+ *divisor = best_divisor;
+
+ DEBUGP("timeout %u usec, prescaler = %u, divisor = %u\n",
+ timeout, best_prescaler, best_divisor);
+
+ return 0;
+}
+
+static int
+rc632_timer_set(struct rfid_asic_handle *handle,
+ u_int64_t timeout)
+{
+ int ret;
+ u_int8_t prescaler, divisor;
+
+ ret = best_prescaler(timeout, &prescaler, &divisor);
+
+ ret = rc632_reg_write(handle, RC632_REG_TIMER_CLOCK,
+ prescaler & 0x1f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_TIMER_CONTROL,
+ RC632_TMR_START_TX_END|RC632_TMR_STOP_RX_BEGIN);
+
+ /* clear timer irq bit */
+ ret = rc632_set_bits(handle, RC632_REG_INTERRUPT_RQ, RC632_IRQ_TIMER);
+
+ ret |= rc632_reg_write(handle, RC632_REG_TIMER_RELOAD, divisor);
+
+ return ret;
+}
+
+/* Wait until RC632 is idle or TIMER IRQ has happened */
+static int rc632_wait_idle_timer(struct rfid_asic_handle *handle)
+{
+ int ret;
+ u_int8_t irq, cmd;
+
+ while (1) {
+ rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &irq);
+ rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &irq);
+ ret = rc632_reg_read(handle, RC632_REG_INTERRUPT_RQ, &irq);
+ if (ret < 0)
+ return ret;
+
+ /* FIXME: currently we're lazy: If we actually received
+ * something even after the timer expired, we accept it */
+ if (irq & RC632_IRQ_TIMER && !(irq & RC632_IRQ_RX)) {
+ u_int8_t foo;
+ rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &foo);
+ if (foo & 0x04)
+ rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &foo);
+
+ return -110;
+ }
+
+ ret = rc632_reg_read(handle, RC632_REG_COMMAND, &cmd);
+ if (ret < 0)
+ return ret;
+
+ if (cmd == 0)
+ return 0;
+
+ /* poll every millisecond */
+ usleep(1000);
+ }
+}
+
+/* Stupid RC632 implementations don't evaluate interrupts but poll the