+/*
+ * Write these values to preserve register contents under HW changes
+ */
+
+#define STM_USB_EPR_INVARIANT ((1 << STM_USB_EPR_CTR_RX) | \
+ (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | \
+ (STM_USB_EPR_STAT_RX_WRITE_INVARIANT << STM_USB_EPR_STAT_RX) | \
+ (1 << STM_USB_EPR_CTR_TX) | \
+ (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | \
+ (STM_USB_EPR_STAT_TX_WRITE_INVARIANT << STM_USB_EPR_STAT_TX))
+
+#define STM_USB_EPR_INVARIANT_MASK ((1 << STM_USB_EPR_CTR_RX) | \
+ (STM_USB_EPR_DTOG_RX_MASK << STM_USB_EPR_DTOG_RX) | \
+ (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX) | \
+ (1 << STM_USB_EPR_CTR_TX) | \
+ (STM_USB_EPR_DTOG_TX_MASK << STM_USB_EPR_DTOG_TX) | \
+ (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX))
+
+/*
+ * These bits are purely under sw control, so preserve them in the
+ * register by re-writing what was read
+ */
+#define STM_USB_EPR_PRESERVE_MASK ((STM_USB_EPR_EP_TYPE_MASK << STM_USB_EPR_EP_TYPE) | \
+ (1 << STM_USB_EPR_EP_KIND) | \
+ (STM_USB_EPR_EA_MASK << STM_USB_EPR_EA))
+
+/*
+ * Set the state of the specified endpoint register to a new
+ * value. This is tricky because the bits toggle where the new
+ * value is one, and we need to write invariant values in other
+ * spots of the register. This hardware is strange...
+ */
+static void
+_ao_usb_set_stat_tx(int ep, uint32_t stat_tx)
+{
+ uint32_t epr_write, epr_old;
+
+ epr_old = epr_write = stm_usb.epr[ep];
+ epr_write &= STM_USB_EPR_PRESERVE_MASK;
+ epr_write |= STM_USB_EPR_INVARIANT;
+ epr_write |= set_toggle(epr_old,
+ STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX,
+ stat_tx << STM_USB_EPR_STAT_TX);
+ stm_usb.epr[ep] = epr_write;
+}
+
+static void
+ao_usb_set_stat_tx(int ep, uint32_t stat_tx)
+{
+ cli();
+ _ao_usb_set_stat_tx(ep, stat_tx);
+ sei();
+}
+
+static void
+ao_usb_set_stat_rx(int ep, uint32_t stat_rx) {
+ uint32_t epr_write, epr_old;
+
+ cli();
+ epr_write = epr_old = stm_usb.epr[ep];
+ epr_write &= STM_USB_EPR_PRESERVE_MASK;
+ epr_write |= STM_USB_EPR_INVARIANT;
+ epr_write |= set_toggle(epr_old,
+ STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX,
+ stat_rx << STM_USB_EPR_STAT_RX);
+ stm_usb.epr[ep] = epr_write;
+ sei();
+}
+