Merge branch 'master'
[fw/altos] / src / samd21 / samd21.h
diff --git a/src/samd21/samd21.h b/src/samd21/samd21.h
new file mode 100644 (file)
index 0000000..b101c6b
--- /dev/null
@@ -0,0 +1,2102 @@
+/*
+ * Copyright © 2019 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _SAMD21_H_
+#define _SAMD21_H_
+
+#include <stdint.h>
+
+typedef volatile uint64_t      vuint64_t;
+typedef volatile uint32_t      vuint32_t;
+typedef volatile void *                vvoid_t;
+typedef volatile uint16_t      vuint16_t;
+typedef volatile uint8_t       vuint8_t;
+
+struct samd21_pac {
+       vuint32_t       wpclr;
+       vuint32_t       wpset;
+};
+
+extern struct samd21_pac samd21_pac0;
+extern struct samd21_pac samd21_pac1;
+extern struct samd21_pac samd21_pac2;
+
+#define samd21_pac0 (*(struct samd21_pac *) 0x40000000)
+#define samd21_pac1 (*(struct samd21_pac *) 0x41000000)
+#define samd21_pac2 (*(struct samd21_pac *) 0x42000000)
+
+struct samd21_gclk {
+       vuint8_t        ctrl;
+       vuint8_t        status;
+       vuint16_t       clkctrl;
+       vuint32_t       genctrl;
+       vuint32_t       gendiv;
+};
+
+extern struct samd21_gclk samd21_gclk;
+
+#define samd21_gclk    (*(struct samd21_gclk *) 0x40000c00)
+
+#define SAMD21_GCLK_CTRL_SWRST         0
+
+#define SAMD21_GCLK_STATUS_SYNCBUSY    7
+
+#define SAMD21_GCLK_CLKCTRL_ID         0
+#define  SAMD21_GCLK_CLKCTRL_ID_DFLL48M_REF            0
+#define  SAMD21_GCLK_CLKCTRL_ID_DPLL                   1
+#define  SAMD21_GCLK_CLKCTRL_ID_DPLL_32K               2
+#define  SAMD21_GCLK_CLKCTRL_ID_WDT                    3
+#define  SAMD21_GCLK_CLKCTRL_ID_RTC                    4
+#define  SAMD21_GCLK_CLKCTRL_ID_EIC                    5
+#define  SAMD21_GCLK_CLKCTRL_ID_USB                    6
+#define  SAMD21_GCLK_CLKCTRL_ID_EVSYS_CHANNEL_0                0x07
+#define  SAMD21_GCLK_CLKCTRL_ID_EVSYS_CHANNEL_1                0x08
+#define  SAMD21_GCLK_CLKCTRL_ID_EVSYS_CHANNEL_2                0x09
+#define  SAMD21_GCLK_CLKCTRL_ID_EVSYS_CHANNEL_3                0x0a
+#define  SAMD21_GCLK_CLKCTRL_ID_EVSYS_CHANNEL_4                0x0b
+#define  SAMD21_GCLK_CLKCTRL_ID_EVSYS_CHANNEL_5                0x0c
+#define  SAMD21_GCLK_CLKCTRL_ID_EVSYS_CHANNEL_6                0x0d
+#define  SAMD21_GCLK_CLKCTRL_ID_EVSYS_CHANNEL_7                0x0e
+#define  SAMD21_GCLK_CLKCTRL_ID_EVSYS_CHANNEL_8                0e0f
+#define  SAMD21_GCLK_CLKCTRL_ID_EVSYS_CHANNEL_9                0x10
+#define  SAMD21_GCLK_CLKCTRL_ID_EVSYS_CHANNEL_10       0x11
+#define  SAMD21_GCLK_CLKCTRL_ID_EVSYS_CHANNEL_11       0x12
+#define  SAMD21_GCLK_CLKCTRL_ID_SERCOMx_SLOW           0x13
+#define  SAMD21_GCLK_CLKCTRL_ID_SERCOM0_CORE           0x14
+#define  SAMD21_GCLK_CLKCTRL_ID_SERCOM1_CORE           0x15
+#define  SAMD21_GCLK_CLKCTRL_ID_SERCOM2_CORE           0x16
+#define  SAMD21_GCLK_CLKCTRL_ID_SERCOM3_CORE           0x17
+#define  SAMD21_GCLK_CLKCTRL_ID_SERCOM4_CORE           0x18
+#define  SAMD21_GCLK_CLKCTRL_ID_SERCOM5_CORE           0x19
+#define  SAMD21_GCLK_CLKCTRL_ID_TCC0_TCC1              0x1a
+#define  SAMD21_GCLK_CLKCTRL_ID_TCC2_TC3               0x1b
+#define  SAMD21_GCLK_CLKCTRL_ID_TC4_TC5                        0x1c
+#define  SAMD21_GCLK_CLKCTRL_ID_TC6_TC7                        0x1d
+#define  SAMD21_GCLK_CLKCTRL_ID_ADC                    0x1e
+#define  SAMD21_GCLK_CLKCTRL_ID_AC_DIG                 0x1f
+#define  SAMD21_GCLK_CLKCTRL_ID_AC_ANA                 0x20
+#define  SAMD21_GCLK_CLKCTRL_ID_DAC                    0x21
+#define  SAMD21_GCLK_CLKCTRL_ID_PTC                    0x22
+#define  SAMD21_GCLK_CLKCTRL_ID_I2S_0                  0x23
+#define  SAMD21_GCLK_CLKCTRL_ID_I2S_1                  0x24
+#define  SAMD21_GCLK_CLKCTRL_ID_TCC3                   0x25
+
+#define SAMD21_GCLK_CLKCTRL_GEN                8
+#define SAMD21_GCLK_CLKCTRL_CLKEN      14
+#define SAMD21_GCLK_CLKCTRL_WRTLOCK    15
+
+#define SAMD21_GCLK_GENCTRL_ID         0
+#define SAMD21_GCLK_GENCTRL_SRC                8
+#define  SAMD21_GCLK_GENCTRL_SRC_XOSC          0
+#define  SAMD21_GCLK_GENCTRL_SRC_GCLKIN                1
+#define  SAMD21_GCLK_GENCTRL_SRC_GCLKGEN1      2
+#define  SAMD21_GCLK_GENCTRL_SRC_OSCULP32K     3
+#define  SAMD21_GCLK_GENCTRL_SRC_OSC32K                4
+#define  SAMD21_GCLK_GENCTRL_SRC_XOSC32K       5
+#define  SAMD21_GCLK_GENCTRL_SRC_OSC8M         6
+#define  SAMD21_GCLK_GENCTRL_SRC_DFLL48M       7
+#define  SAMD21_GCLK_GENCTRL_SRC_FDPLL96M      8
+
+#define SAMD21_GCLK_GENCTRL_GENEN      16
+#define SAMD21_GCLK_GENCTRL_IDC                17
+#define SAMD21_GCLK_GENCTRL_OOV                18
+#define SAMD21_GCLK_GENCTRL_OE         19
+#define SAMD21_GCLK_GENCTRL_DIVSEL     20
+#define SAMD21_GCLK_GENCTRL_RUNSTDBY   21
+
+#define SAMD21_GCLK_GENDIV_ID          0
+#define SAMD21_GCLK_GENDIV_DIV         8
+
+struct samd21_pm {
+       vuint8_t        ctrl;
+       vuint8_t        sleep;
+       vuint8_t        reserved_02;
+       vuint8_t        reserved_03;
+       vuint32_t       reserved_04;
+       vuint8_t        cpusel;
+       vuint8_t        apbasel;
+       vuint8_t        apbbsel;
+       vuint8_t        apbcsel;
+       vuint32_t       reserved_0c;
+
+       vuint32_t       reserved_10;
+       vuint32_t       ahbmask;
+       vuint32_t       apbamask;
+       vuint32_t       apbbmask;
+
+       vuint32_t       apbcmask;
+       vuint32_t       reserved_24;
+       vuint32_t       reserved_28;
+       vuint32_t       reserved_2c;
+
+       vuint32_t       reserved_30;
+       vuint8_t        intenclr;
+       vuint8_t        intelset;
+       vuint8_t        intflag;
+       vuint8_t        reserved_37;
+       vuint8_t        rcause;
+};
+
+extern struct samd21_pm samd21_pm;
+
+#define samd21_pm      (*(struct samd21_pm *) 0x40000400)
+
+#define SAMD21_PM_CPUSEL_CPUDIV                0
+#define SAMD21_PM_APBASEL_APBADIV      0
+#define SAMD21_PM_APBBSEL_APBBDIV      0
+#define SAMD21_PM_APBCSEL_APBCDIV      0
+
+#define SAMD21_PM_APBAMASK_PAC0                0
+#define SAMD21_PM_APBAMASK_PM          1
+#define SAMD21_PM_APBAMASK_SYSCTRL     2
+#define SAMD21_PM_APBAMASK_GCLK                3
+#define SAMD21_PM_APBAMASK_WDT         4
+#define SAMD21_PM_APBAMASK_RTC         5
+#define SAMD21_PM_APBAMASK_EIC         6
+
+#define SAMD21_PM_AHBMASK_HPB0         0
+#define SAMD21_PM_AHBMASK_HPB1         1
+#define SAMD21_PM_AHBMASK_HPB2         2
+#define SAMD21_PM_AHBMASK_DSU          3
+#define SAMD21_PM_AHBMASK_NVMCTRL      4
+#define SAMD21_PM_AHBMASK_DMAC         5
+#define SAMD21_PM_AHBMASK_USB          6
+
+#define SAMD21_PM_APBBMASK_PAC1                0
+#define SAMD21_PM_APBBMASK_DSU         1
+#define SAMD21_PM_APBBMASK_NVMCTRL     2
+#define SAMD21_PM_APBBMASK_PORT                3
+#define SAMD21_PM_APBBMASK_DMAC                4
+#define SAMD21_PM_APBBMASK_USB         5
+
+#define SAMD21_PM_APBCMASK_PAC2                0
+#define SAMD21_PM_APBCMASK_EVSYS       1
+#define SAMD21_PM_APBCMASK_SERCOM0     2
+#define SAMD21_PM_APBCMASK_SERCOM1     3
+#define SAMD21_PM_APBCMASK_SERCOM2     4
+#define SAMD21_PM_APBCMASK_SERCOM3     5
+#define SAMD21_PM_APBCMASK_SERCOM4     6
+#define SAMD21_PM_APBCMASK_SERCOM5     7
+#define SAMD21_PM_APBCMASK_TCC0                8
+#define SAMD21_PM_APBCMASK_TCC1                9
+#define SAMD21_PM_APBCMASK_TCC2                10
+#define SAMD21_PM_APBCMASK_TC3         11
+#define SAMD21_PM_APBCMASK_TC4         12
+#define SAMD21_PM_APBCMASK_TC5         13
+#define SAMD21_PM_APBCMASK_TC6         14
+#define SAMD21_PM_APBCMASK_TC7         15
+#define SAMD21_PM_APBCMASK_ADC         16
+#define SAMD21_PM_APBCMASK_AC          17
+#define SAMD21_PM_APBCMASK_DAC         18
+#define SAMD21_PM_APBCMASK_PTC         19
+#define SAMD21_PM_APBCMASK_I2S         20
+#define SAMD21_PM_APBCMASK_AC1         21
+#define SAMD21_PM_APBCMASK_TCC3                24
+
+struct samd21_sysctrl {
+       vuint32_t       intenclr;
+       vuint32_t       intenset;
+       vuint32_t       intflag;
+       vuint32_t       pclksr;
+
+       vuint32_t       xosc;
+       vuint32_t       xosc32k;
+       vuint32_t       osc32k;
+       vuint32_t       osculp32k;
+
+       vuint32_t       osc8m;
+       vuint32_t       dfllctrl;
+       vuint32_t       dfllval;
+       vuint32_t       dfllmul;
+
+       vuint32_t       dfllsync;
+       vuint32_t       bod33;
+       vuint32_t       reserved_38;
+       vuint32_t       vreg;
+
+       vuint32_t       vref;
+       vuint32_t       dpllctrla;
+       vuint32_t       dpllratio;
+       vuint32_t       dpllctrlb;
+
+       vuint32_t       dpllstatus;
+};
+
+extern struct samd21_sysctrl samd21_sysctrl;
+
+#define samd21_sysctrl (*(struct samd21_sysctrl *) 0x40000800)
+
+#define SAMD21_SYSCTRL_PCLKSR_XOSCRDY          0
+#define SAMD21_SYSCTRL_PCLKSR_XOSC32KRDY       1
+#define SAMD21_SYSCTRL_PCLKSR_OSC32KRDY                2
+#define SAMD21_SYSCTRL_PCLKSR_OSC8MRDY         3
+#define SAMD21_SYSCTRL_PCLKSR_DFLLRDY          4
+#define SAMD21_SYSCTRL_PCLKSR_DFLLOOB          5
+#define SAMD21_SYSCTRL_PCLKSR_DFLLLCKF         6
+#define SAMD21_SYSCTRL_PCLKSR_DFLLLCKC         7
+#define SAMD21_SYSCTRL_PCLKSR_DFLLRCS          8
+#define SAMD21_SYSCTRL_PCLKSR_BOD33RDY         9
+#define SAMD21_SYSCTRL_PCLKSR_BOD33DET         10
+#define SAMD21_SYSCTRL_PCLKSR_B33SRDY          11
+#define SAMD21_SYSCTRL_PCLKSR_DBPLLLCKR                15
+#define SAMD21_SYSCTRL_PCLKSR_DPLLLCKF         16
+#define SAMD21_SYSCTRL_PCLKSR_DPLLTO           17
+
+#define SAMD21_SYSCTRL_XOSC_ENABLE             1
+#define SAMD21_SYSCTRL_XOSC_XTALEN             2
+#define SAMD21_SYSCTRL_XOSC_RUNSTDBY           6
+#define SAMD21_SYSCTRL_XOSC_ONDEMAND           7
+#define SAMD21_SYSCTRL_XOSC_GAIN               8
+#define  SAMD21_SYSCTRL_XOSC_GAIN_2MHz                 0
+#define  SAMD21_SYSCTRL_XOSC_GAIN_4MHz                 1
+#define  SAMD21_SYSCTRL_XOSC_GAIN_8MHz                 2
+#define  SAMD21_SYSCTRL_XOSC_GAIN_16MHz                        3
+#define  SAMD21_SYSCTRL_XOSC_GAIN_30MHz                        4
+#define SAMD21_SYSCTRL_XOSC_AMPGC              11
+#define SAMD21_SYSCTRL_XOSC_STARTUP            12
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_1                 0
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_2                         1
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_4                 2
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_8                 3
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_16                        4
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_32                        5
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_64                        6
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_128               7
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_256               8
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_512               9
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_1024              10
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_2048              11
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_4096              12
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_8192              13
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_16384             14
+#define  SAMD21_SYSCTRL_XOSC_STARTUP_32768             15
+
+#define SAMD21_SYSCTRL_XOSC32K_ENABLE  1
+#define SAMD21_SYSCTRL_XOSC32K_XTALEN  2
+#define SAMD21_SYSCTRL_XOSC32K_EN32K   3
+#define SAMD21_SYSCTRL_XOSC32K_AAMPEN  5
+#define SAMD21_SYSCTRL_XOSC32K_RUNSTDBY        6
+#define SAMD21_SYSCTRL_XOSC32K_ONDEMAND        7
+#define SAMD21_SYSCTRL_XOSC32K_STARTUP 8
+#define SAMD21_SYSCTRL_XOSC32K_WRTLOCK 12
+
+#define SAMD21_SYSCTRL_OSC8M_ENABLE    1
+#define SAMD21_SYSCTRL_OSC8M_RUNSTDBY  6
+#define SAMD21_SYSCTRL_OSC8M_ONDEMAND  7
+#define SAMD21_SYSCTRL_OSC8M_PRESC     8
+#define  SAMD21_SYSCTRL_OSC8M_PRESC_1          0
+#define  SAMD21_SYSCTRL_OSC8M_PRESC_2          1
+#define  SAMD21_SYSCTRL_OSC8M_PRESC_4          2
+#define  SAMD21_SYSCTRL_OSC8M_PRESC_8          3
+#define  SAMD21_SYSCTRL_OSC8M_PRESC_MASK       3
+#define SAMD21_SYSCTRL_OSC8M_CALIB     16
+#define SAMD21_SYSCTRL_OSC8M_FRANGE    30
+#define  SAMD21_SYSCTRL_OSC8M_FRANGE_4_6       0
+#define  SAMD21_SYSCTRL_OSC8M_FRANGE_6_8       1
+#define  SAMD21_SYSCTRL_OSC8M_FRANGE_8_11      2
+#define  SAMD21_SYSCTRL_OSC8M_FRANGE_11_15     3
+
+#define SAMD21_SYSCTRL_DFLLCTRL_ENABLE         1
+#define SAMD21_SYSCTRL_DFLLCTRL_MODE           2
+#define SAMD21_SYSCTRL_DFLLCTRL_STABLE         3
+#define SAMD21_SYSCTRL_DFLLCTRL_LLAW           4
+#define SAMD21_SYSCTRL_DFLLCTRL_USBCRM         5
+#define SAMD21_SYSCTRL_DFLLCTRL_RUNSTDBY       6
+#define SAMD21_SYSCTRL_DFLLCTRL_ONDEMAND       7
+#define SAMD21_SYSCTRL_DFLLCTRL_CCDIS          8
+#define SAMD21_SYSCTRL_DFLLCTRL_QLDIS          9
+#define SAMD21_SYSCTRL_DFLLCTRL_BPLCKC         10
+#define SAMD21_SYSCTRL_DFLLCTRL_WAITLOCK       11
+
+#define SAMD21_SYSCTRL_DFLLVAL_FINE            0
+#define SAMD21_SYSCTRL_DFLLVAL_COARSE          10
+#define SAMD21_SYSCTRL_DFLLVAL_DIFF            16
+
+#define SAMD21_SYSCTRL_DFLLMUL_MUL             0
+#define SAMD21_SYSCTRL_DFLLMUL_FSTEP           16
+#define SAMD21_SYSCTRL_DFLLMUL_CSTEP           26
+
+#define SAMD21_SYSCTRL_DFLLSYNC_READREQ                7
+
+#define SAMD21_SYSCTRL_DPLLCTRLA_ENABLE                1
+#define SAMD21_SYSCTRL_DPLLCTRLA_RUNSTDBY      6
+#define SAMD21_SYSCTRL_DPLLCTRLA_ONDEMAND      7
+
+#define SAMD21_SYSCTRL_DPLLRATIO_LDR           0
+#define SAMD21_SYSCTRL_DPLLRATIO_LDRFRAC       0
+
+#define SAMD21_SYSCTRL_DPLLCTRLB_FILTER                0
+#define  SAMD21_SYSCTRL_DPLLCTRLB_FILTER_DEFAULT       0
+#define  SAMD21_SYSCTRL_DPLLCTRLB_FILTER_LBFILT                1
+#define  SAMD21_SYSCTRL_DPLLCTRLB_FILTER_HBFILT                2
+#define  SAMD21_SYSCTRL_DPLLCTRLB_FILTER_HDFILT                3
+#define SAMD21_SYSCTRL_DPLLCTRLB_LPEN          2
+#define SAMD21_SYSCTRL_DPLLCTRLB_WUF           3
+#define SAMD21_SYSCTRL_DPLLCTRLB_REFCLK                4
+#define  SAMD21_SYSCTRL_DPLLCTRLB_REFCLK_XOSC32                0
+#define  SAMD21_SYSCTRL_DPLLCTRLB_REFCLK_XOSC          1
+#define  SAMD21_SYSCTRL_DPLLCTRLB_REFCLK_GCLK_DPLL     2
+#define SAMD21_SYSCTRL_DPLLCTRLB_LTIME         8
+#define  SAMD21_SYSCTRL_DPLLCTRLB_LTIME_DEFAULT                0
+#define  SAMD21_SYSCTRL_DPLLCTRLB_LTIME_8MS            4
+#define  SAMD21_SYSCTRL_DPLLCTRLB_LTIME_9MS            5
+#define  SAMD21_SYSCTRL_DPLLCTRLB_LTIME_10MS           6
+#define  SAMD21_SYSCTRL_DPLLCTRLB_LTIME_11MS           7
+#define SAMD21_SYSCTRL_DPLLCTRLB_LBYPASS       12
+#define SAMD21_SYSCTRL_DPLLCTRLB_DIV           16
+
+#define SAMD21_SYSCTRL_DPLLSTATUS_LOCK         0
+#define SAMD21_SYSCTRL_DPLLSTATUS_CLKRDY       1
+#define SAMD21_SYSCTRL_DPLLSTATUS_ENABLE       2
+#define SAMD21_SYSCTRL_DPLLSTATUS_DIV          3
+
+struct samd21_dmac {
+       vuint16_t       ctrl;
+       vuint16_t       crcctrl;
+       vuint32_t       crcdatain;
+       vuint32_t       crcchksum;
+       vuint8_t        crcstatus;
+       vuint8_t        dbgctrl;
+       vuint8_t        qosctrl;
+       uint8_t         reserved_0f;
+
+       vuint32_t       swtrigctrl;
+       vuint32_t       prictrl0;
+       uint32_t        reserved_18;
+       uint32_t        reserved_1c;
+
+       vuint16_t       intpend;
+       uint16_t        reserved_22;
+       vuint32_t       intstatus;
+       vuint32_t       busych;
+       vuint32_t       pendch;
+
+       vuint32_t       active;
+       vuint32_t       baseaddr;
+       vuint32_t       wrbaddr;
+       uint16_t        reserved_3c;
+       uint8_t         reserved_3e;
+       vuint8_t        chid;
+
+       vuint8_t        chctrla;
+       uint8_t         reserved_41;
+       uint16_t        reserved_42;
+       vuint32_t       chctrlb;
+       uint32_t        reserved_48;
+       vuint8_t        chintenclr;
+       vuint8_t        chintenset;
+       vuint8_t        chintflag;
+       vuint8_t        chstatus;
+};
+
+extern struct samd21_dmac samd21_dmac;
+
+#define samd21_dmac (*(struct samd21_dmac *) 0x41004800)
+
+struct samd21_dmac_desc {
+       vuint16_t       btctrl;
+       vuint16_t       btcnt;
+       vuint32_t       srcaddr;
+       vuint32_t       dstaddr;
+       vuint32_t       descaddr;
+} __attribute__((aligned(8)));
+
+#define SAMD21_DMAC_NCHAN              12
+
+#define SAMD21_DMAC_CTRL_SWRST         0
+#define SAMD21_DMAC_CTRL_DMAENABLE     1
+#define SAMD21_DMAC_CTRL_CRCENABLE     2
+#define SAMD21_DMAC_CTRL_LVLEN(x)      (8 + (x))
+
+#define SAMD21_DMAC_QOSCTRL_WRBQOS     0
+#define SAMD21_DMAC_QOSCTRL_FQOS       2
+#define SAMD21_DMAC_QOSCTRL_DQOS       4
+
+#define SAMD21_DMAC_QOSCTRL_DISABLE    0
+#define SAMD21_DMAC_QOSCTRL_LOW                1
+#define SAMD21_DMAC_QOSCTRL_MEDIUM     2
+#define SAMD21_DMAC_QOSCTRL_HIGH       3
+
+#define SAMD21_DMAC_SWTRIGCTRL_SWTRIG(n)       (0 + (n))
+
+#define SAMD21_DMAC_PRICTRL0_LVLPRI0   0
+#define SAMD21_DMAC_PRICTRL0_RRLVLEN0  7
+#define SAMD21_DMAC_PRICTRL0_LVLPRI1   8
+#define SAMD21_DMAC_PRICTRL0_RRLVLEN1  15
+#define SAMD21_DMAC_PRICTRL0_LVLPRI2   16
+#define SAMD21_DMAC_PRICTRL0_RRLVLEN2  23
+#define SAMD21_DMAC_PRICTRL0_LVLPRI3   24
+#define SAMD21_DMAC_PRICTRL0_RRLVLEN3  31
+
+#define SAMD21_DMAC_INTPEND_ID         0
+#define  SAMD21_DMAC_INTPEND_ID_MASK           0xf
+#define SAMD21_DMAC_INTPEND_TERR       8
+#define SAMD21_DMAC_INTPEND_TCMPL      9
+#define SAMD21_DMAC_INTPEND_SUSP       10
+#define SAMD21_DMAC_INTPEND_FERR       13
+#define SAMD21_DMAC_INTPEND_BUSY       14
+#define SAMD21_DMAC_INTPEND_PEND       15
+
+#define SAMD21_DMAC_INTSTATUS_CHINT(n) (0 + (n))
+
+#define SAMD21_DMAC_BUSYCH_BUSYCH(n)   (0 + (n))
+
+#define SAMD21_DMAC_PENDCH_PENDCH(n)   (0 + (n))
+
+#define SAMD21_DMAC_ACTIVE_LVLEX(x)    (0 + (x))
+#define SAMD21_DMAC_ACTIVE_ID          8
+#define SAMD21_DMAC_ACTIVE_ABUSY       15
+#define SAMD21_DMAC_ACTIVE_BTCNT       16
+
+#define SAMD21_DMAC_CHCTRLA_SWRST      0
+#define SAMD21_DMAC_CHCTRLA_ENABLE     1
+
+#define SAMD21_DMAC_CHCTRLB_EVACT      0
+#define  SAMD21_DMAC_CHCTRLB_EVACT_NOACT       0
+#define  SAMD21_DMAC_CHCTRLB_EVACT_TRIG                1
+#define  SAMD21_DMAC_CHCTRLB_EVACT_CTRIG       2
+#define  SAMD21_DMAC_CHCTRLB_EVACT_CBLOCK      3
+#define  SAMD21_DMAC_CHCTRLB_EVACT_SUSPEND     4
+#define  SAMD21_DMAC_CHCTRLB_EVACT_RESUME      5
+#define  SAMD21_DMAC_CHCTRLB_EVACT_SSKIP       6
+
+#define SAMD21_DMAC_CHCTRLB_EVIE       3
+#define SAMD21_DMAC_CHCTRLB_EVOE       4
+#define SAMD21_DMAC_CHCTRLB_LVL                5
+#define  SAMD21_DMAC_CHCTRLB_LVL_LVL0          0UL
+#define  SAMD21_DMAC_CHCTRLB_LVL_LVL1          1UL
+#define  SAMD21_DMAC_CHCTRLB_LVL_LVL2          2UL
+#define  SAMD21_DMAC_CHCTRLB_LVL_LVL3          3UL
+#define SAMD21_DMAC_CHCTRLB_TRIGSRC    8
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_DISABLE   0x00UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_SERCOM_RX(n)      (0x01UL + (n) * 2UL)
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_SERCOM_TX(n)      (0x02UL + (n) * 2UL)
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC0_OVF  0x0dUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC0_MC0  0x0eUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC0_MC1  0x0fUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC0_MC2  0x10UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC0_MC3  0x11UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC1_OVF  0x12UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC1_MC0  0x13UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC1_MC1  0x14UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC2_OVF  0x15UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC2_MC0  0x16UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC2_MC1  0x17UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC3_OVF   0x18UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC3_MC0   0x19UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC3_MC1   0x1aUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC4_OVF   0x1bUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC4_MC0   0x1cUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC4_MC1   0x1dUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC5_OVF   0x1eUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC5_MC0   0x1fUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC5_MC1   0x20UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC6_OVF   0x21UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC6_MC0   0x22UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC6_MC1   0x23UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC7_OVF   0x24UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC7_MC0   0x25UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TC7_MC1   0x26UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_ADC_RESRDY        0x27UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_DAC_EMPTY 0x28UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_I2S_RX_0  0x29UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_I2S_RX_1  0x2aUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_I2S_TX_0  0x2bUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_I2S_TX_1  0x2cUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC3_OVF  0x2dUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC3_MC0  0x2eUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC3_MC1  0x2fUL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC3_MC2  0x30UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGSRC_TCC3_MC3  0x31UL
+
+#define SAMD21_DMAC_CHCTRLB_TRIGACT    22
+#define  SAMD21_DMAC_CHCTRLB_TRIGACT_BLOCK             0UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGACT_BEAT              2UL
+#define  SAMD21_DMAC_CHCTRLB_TRIGACT_TRANSACTION       3UL
+
+#define SAMD21_DMAC_CHCTRLB_CMD                24
+#define  SAMD21_DMAC_CHCTRLB_CMD_NOACT         0UL
+#define  SAMD21_DMAC_CHCTRLB_CMD_SUSPEND       1UL
+#define  SAMD21_DMAC_CHCTRLB_CMD_RESUME                2UL
+
+#define SAMD21_DMAC_CHINTFLAG_TERR     0
+#define SAMD21_DMAC_CHINTFLAG_TCMPL    1
+#define SAMD21_DMAC_CHINTFLAG_SUSP     2
+
+#define SAMD21_DMAC_CHSTATUS_PEND      0
+#define SAMD21_DMAC_CHSTATUS_BUSY      1
+#define SAMD21_DMAC_CHSTATUS_FERR      2
+
+#define SAMD21_DMAC_DESC_BTCTRL_VALID          0
+#define SAMD21_DMAC_DESC_BTCTRL_EVOSEL         1
+#define  SAMD21_DMAC_DESC_BTCTRL_EVOSEL_DISABLE                0UL
+#define  SAMD21_DMAC_DESC_BTCTRL_EVOSEL_BLOCK          1UL
+#define  SAMD21_DMAC_DESC_BTCTRL_EVOSEL_BEAT           3UL
+#define SAMD21_DMAC_DESC_BTCTRL_BLOCKACT       3
+#define  SAMD21_DMAC_DESC_BTCTRL_BLOCKACT_NOACT                0UL
+#define  SAMD21_DMAC_DESC_BTCTRL_BLOCKACT_INT          1UL
+#define  SAMD21_DMAC_DESC_BTCTRL_BLOCKACT_SUSPEND      2UL
+#define  SAMD21_DMAC_DESC_BTCTRL_BLOCKACT_BOTH         3UL
+#define SAMD21_DMAC_DESC_BTCTRL_BEATSIZE       8
+#define  SAMD21_DMAC_DESC_BTCTRL_BEATSIZE_BYTE         0UL
+#define  SAMD21_DMAC_DESC_BTCTRL_BEATSIZE_HWORD                1UL
+#define  SAMD21_DMAC_DESC_BTCTRL_BEATSIZE_WORD         2UL
+#define SAMD21_DMAC_DESC_BTCTRL_SRCINC         10
+#define SAMD21_DMAC_DESC_BTCTRL_DSTINC         11
+#define SAMD21_DMAC_DESC_BTCTRL_STEPSEL                12
+#define  SAMD21_DMAC_DESC_BTCTRL_STEPSEL_DST           0UL
+#define  SAMD21_DMAC_DESC_BTCTRL_STEPSEL_SRC           1UL
+#define SAMD21_DMAC_DESC_BTCTRL_STEPSIZE       13
+#define  SAMD21_DMAC_DESC_BTCTRL_STEPSIZE_X1           0UL
+#define  SAMD21_DMAC_DESC_BTCTRL_STEPSIZE_X2           1UL
+#define  SAMD21_DMAC_DESC_BTCTRL_STEPSIZE_X4           2UL
+#define  SAMD21_DMAC_DESC_BTCTRL_STEPSIZE_X8           3UL
+#define  SAMD21_DMAC_DESC_BTCTRL_STEPSIZE_X16          4UL
+#define  SAMD21_DMAC_DESC_BTCTRL_STEPSIZE_X32          5UL
+#define  SAMD21_DMAC_DESC_BTCTRL_STEPSIZE_X64          6UL
+#define  SAMD21_DMAC_DESC_BTCTRL_STEPSIZE_X128         7UL
+
+struct samd21_eic {
+       vuint8_t        ctrl;
+       vuint8_t        status;
+       vuint8_t        nmictrl;
+       vuint8_t        nmiflag;
+       vuint32_t       evctrl;
+       vuint32_t       intenclr;
+       vuint32_t       intenset;
+
+       vuint32_t       intflag;
+       vuint32_t       wakeup;
+       vuint32_t       config[2];
+};
+
+extern struct samd21_eic samd21_eic;
+
+#define samd21_eic     (*(struct samd21_eic *) 0x40001800)
+
+#define SAMD21_NUM_EIC                 16
+
+#define SAMD21_EIC_CTRL_ENABLE         1
+#define SAMD21_EIC_CTRL_SWRST          0
+
+#define SAMD21_EIC_STATUS_SYNCBUSY     7
+
+#define SAMD21_EIC_NMICTRL_NMIFILTEN   3
+#define SAMD21_EIC_NMICTRL_NMISENSE    0
+
+#define SAMD21_EIC_NMIFLAG_NMI         0
+
+#define SAMD21_EIC_EVCTRL_EXTINTEO(n)  (n)
+
+#define SAMD21_EIC_INTENCLR_EXTINT(n)  (n)
+
+#define SAMD21_EIC_INTENSET_EXTINT(n)  (n)
+
+#define SAMD21_EIC_INTFLAG_EXTINT(n)   (n)
+#define SAMD21_EIC_WAKEUP_WAKEUPEN(n)  (n)
+#define SAMD21_EIC_CONFIG_N(n)         ((n) >> 3)
+#define SAMD21_EIC_CONFIG_SENSE(n)     (((n) & 7) << 2)
+#define SAMD21_EIC_CONFIG_FILTEN(n)    (SAMD21_EIC_CONFIG_SENSE(n) + 3)
+#define  SAMD21_EIC_CONFIG_SENSE_NONE          0
+#define  SAMD21_EIC_CONFIG_SENSE_RISE          1
+#define  SAMD21_EIC_CONFIG_SENSE_FALL          2
+#define  SAMD21_EIC_CONFIG_SENSE_BOTH          3
+#define  SAMD21_EIC_CONFIG_SENSE_HIGH          4
+#define  SAMD21_EIC_CONFIG_SENSE_LOW           5
+#define  SAMD21_EIC_CONFIG_SENSE_MASK          7UL
+
+struct samd21_nvmctrl {
+       vuint32_t       ctrla;
+       vuint32_t       ctrlb;
+       vuint32_t       param;
+       vuint32_t       intenclr;
+
+       vuint32_t       intenset;
+       vuint32_t       intflag;
+       vuint32_t       status;
+       vuint32_t       addr;
+
+       vuint32_t       lock;
+};
+
+extern struct samd21_nvmctrl samd21_nvmctrl;
+
+#define samd21_nvmctrl (*(struct samd21_nvmctrl *) 0x41004000)
+
+#define SAMD21_NVMCTRL_CTRLA_CMD       0
+#define  SAMD21_NVMCTRL_CTRLA_CMD_ER           0x02
+#define  SAMD21_NVMCTRL_CTRLA_CMD_WP           0x04
+#define  SAMD21_NVMCTRL_CTRLA_CMD_EAR          0x05
+#define  SAMD21_NVMCTRL_CTRLA_CMD_WAP          0x06
+#define  SAMD21_NVMCTRL_CTRLA_CMD_RWWEEER      0x1a
+#define  SAMD21_NVMCTRL_CTRLA_CMD_RWEEEWP      0x1c
+#define  SAMD21_NVMCTRL_CTRLA_CMD_LR           0x40
+#define  SAMD21_NVMCTRL_CTRLA_CMD_UR           0x41
+#define  SAMD21_NVMCTRL_CTRLA_CMD_SPRM         0x42
+#define  SAMD21_NVMCTRL_CTRLA_CMD_CPRM         0x43
+#define  SAMD21_NVMCTRL_CTRLA_CMD_PBC          0x44
+#define  SAMD21_NVMCTRL_CTRLA_CMD_SSB          0x45
+#define  SAMD21_NVMCTRL_CTRLA_CMD_INVALL       0x46
+#define  SAMD21_NVMCTRL_CTRLA_CMD_LDR          0x47
+#define  SAMD21_NVMCTRL_CTRLA_CMD_UDR          0x48
+#define SAMD21_NVMCTRL_CTRLA_CMDEX     8
+#define  SAMD21_NVMCTRL_CTRLA_CMDEX_KEY                0xa5
+
+#define SAMD21_NVMCTRL_CTRLB_RWS       1
+#define SAMD21_NVMCTRL_CTRLB_MANW      7
+#define SAMD21_NVMCTRL_CTRLB_SLEEPRM   8
+#define SAMD21_NVMCTRL_CTRLB_READMODE  16
+#define SAMD21_NVMCTRL_CTRLB_CACHEDIS  18
+
+#define SAMD21_NVMCTRL_INTENCLR_READY  0
+#define SAMD21_NVMCTRL_INTENCLR_ERROR  1
+
+#define SAMD21_NVMCTRL_INTENSET_READY  0
+#define SAMD21_NVMCTRL_INTENSET_ERROR  1
+
+#define SAMD21_NVMCTRL_INTFLAG_READY   0
+#define SAMD21_NVMCTRL_INTFLAG_ERROR   1
+
+#define SAMD21_NVMCTRL_STATUS_PRM      0
+#define SAMD21_NVMCTRL_STATUS_LOAD     1
+#define SAMD21_NVMCTRL_STATUS_PROGE    2
+#define SAMD21_NVMCTRL_STATUS_LOCKE    3
+#define SAMD21_NVMCTRL_STATUS_NVME     4
+#define SAMD21_NVMCTRL_STATUS_SB       8
+
+#define SAMD21_NVMCTRL_PARAM_NVMP      0
+#define  SAMD21_NVMCTRL_PARAM_NVMP_MASK                0xffff
+#define SAMD21_NVMCTRL_PARAM_PSZ       16
+#define  SAMD21_NVMCTRL_PARAM_PSZ_MASK         0x7
+#define SAMD21_NVMCTRL_PARAM_RWWEEP    20
+#define  SAMD21_NVMCTRL_PARAM_RWWEEP_MASK      0xfff
+
+static inline uint32_t
+samd21_nvmctrl_page_shift(void)
+{
+       return(3 + ((samd21_nvmctrl.param >> SAMD21_NVMCTRL_PARAM_PSZ) &
+                   SAMD21_NVMCTRL_PARAM_PSZ_MASK));
+}
+
+static inline uint32_t
+samd21_nvmctrl_page_size(void)
+{
+       return 1 << samd21_nvmctrl_page_shift();
+}
+
+uint32_t
+samd21_flash_size(void);
+
+struct samd21_port {
+       vuint32_t       dir;
+       vuint32_t       dirclr;
+       vuint32_t       dirset;
+       vuint32_t       dirtgl;
+
+       vuint32_t       out;
+       vuint32_t       outclr;
+       vuint32_t       outset;
+       vuint32_t       outtgl;
+
+       vuint32_t       in;
+       vuint32_t       ctrl;
+       vuint32_t       wrconfig;
+       vuint32_t       reserved_2c;
+
+       vuint8_t        pmux[16];
+
+       vuint8_t        pincfg[32];
+};
+
+extern struct samd21_port samd21_port_a;
+extern struct samd21_port samd21_port_b;
+
+#define samd21_port_a (*(struct samd21_port *) 0x41004400)
+#define samd21_port_b (*(struct samd21_port *) 0x41004480)
+
+#define SAMD21_PORT_PINCFG_PMUXEN      0
+#define SAMD21_PORT_PINCFG_INEN                1
+#define SAMD21_PORT_PINCFG_PULLEN      2
+#define SAMD21_PORT_PINCFG_DRVSTR      6
+
+#define SAMD21_PORT_PMUX_FUNC_A                0
+#define SAMD21_PORT_PMUX_FUNC_B                1
+#define SAMD21_PORT_PMUX_FUNC_C                2
+#define SAMD21_PORT_PMUX_FUNC_D                3
+#define SAMD21_PORT_PMUX_FUNC_E                4
+#define SAMD21_PORT_PMUX_FUNC_F                5
+#define SAMD21_PORT_PMUX_FUNC_G                6
+#define SAMD21_PORT_PMUX_FUNC_H                7
+#define SAMD21_PORT_PMUX_FUNC_I                8
+
+#define SAMD21_PORT_DIR_OUT            1
+#define SAMD21_PORT_DIR_IN             0
+
+static inline void
+samd21_port_dir_set(struct samd21_port *port, uint8_t pin, uint8_t dir)
+{
+       if (dir)
+               port->dirset = (1 << pin);
+       else
+               port->dirclr = (1 << pin);
+}
+
+static inline void
+samd21_port_pincfg_set(struct samd21_port *port, uint8_t pin, uint8_t pincfg_mask, uint8_t pincfg)
+{
+       port->pincfg[pin] = (uint8_t) ((port->pincfg[pin] & ~pincfg_mask) | pincfg);
+}
+
+static inline uint8_t
+samd21_port_pincfg_get(struct samd21_port *port, uint8_t pin)
+{
+       return port->pincfg[pin];
+}
+
+static inline void
+samd21_port_pmux_set(struct samd21_port *port, uint8_t pin, uint8_t func)
+{
+       uint8_t byte = pin >> 1;
+       uint8_t bit = (pin & 1) << 2;
+       uint8_t mask = 0xf << bit;
+       uint8_t value = (uint8_t) ((port->pmux[byte] & ~mask) | (func << bit));
+       port->pmux[byte] = value;
+       samd21_port_pincfg_set(port, pin,
+                              (1 << SAMD21_PORT_PINCFG_PMUXEN),
+                              (1 << SAMD21_PORT_PINCFG_PMUXEN));
+}
+
+static inline uint8_t
+samd21_port_pmux_get(struct samd21_port *port, uint8_t pin)
+{
+       uint8_t byte = pin >> 1;
+       uint8_t bit = (pin & 1) << 2;
+       uint8_t mask = 0xf << bit;
+       uint8_t value = (uint8_t) ((port->pmux[byte] & mask) >> bit);
+       return value;
+}
+
+static inline void
+samd21_port_pmux_clr(struct samd21_port *port, uint8_t pin)
+{
+       samd21_port_pincfg_set(port, pin,
+                              (0 << SAMD21_PORT_PINCFG_PMUXEN),
+                              (1 << SAMD21_PORT_PINCFG_PMUXEN));
+}
+
+struct samd21_adc {
+       vuint8_t        ctrla;
+       vuint8_t        refctrl;
+       vuint8_t        avgctrl;
+       vuint8_t        sampctrl;
+       vuint16_t       ctrlb;
+       vuint16_t       reserved_06;
+       vuint8_t        winctrl;
+       vuint8_t        reserved_09;
+       vuint16_t       reserved_0a;
+       vuint8_t        swtrig;
+       vuint8_t        reserved_0d;
+       vuint16_t       reserved_0e;
+
+       vuint32_t       inputctrl;
+       vuint8_t        evctrl;
+       vuint8_t        reserved_15;
+       vuint8_t        intenclr;
+       vuint8_t        intenset;
+       vuint8_t        intflag;
+       vuint8_t        status;
+       vuint16_t       result;
+       vuint16_t       winlt;
+       vuint16_t       reserved_1e;
+
+       vuint16_t       winut;
+       vuint16_t       reserved_22;
+       vuint16_t       gaincorr;
+       vuint16_t       offsetcorr;
+       vuint16_t       calib;
+       vuint8_t        dbgctrl;
+       vuint8_t        reserved_2b;
+       vuint32_t       reserved_2c;
+};
+
+#define SAMD21_ADC_CTRLA_SWRST         0
+#define SAMD21_ADC_CTRLA_ENABLE                1
+#define SAMD21_ADC_CTRLA_RUNSTDBY      2
+
+#define SAMD21_ADC_REFCTRL_REFSEL      0
+#define  SAMD21_ADC_REFCTRL_REFSEL_INT1V       0
+#define  SAMD21_ADC_REFCTRL_REFSEL_INTVCC0     1
+#define  SAMD21_ADC_REFCTRL_REFSEL_INTVCC1     2
+#define  SAMD21_ADC_REFCTRL_REFSEL_VREFA       3
+#define  SAMD21_ADC_REFCTRL_REFSEL_VREFB       4
+#define SAMD21_ADC_REFCTRL_REFCOMP     7
+
+#define SAMD21_ADC_AVGCTRL_SAMPLENUM   0
+#define SAMD21_ADC_AVGCTRL_ADJRES      4
+
+#define SAMD21_ADC_SAMPCTRL_SAMPLEN    0
+
+#define SAMD21_ADC_CTRLB_DIFFMODE      0
+#define SAMD21_ADC_CTRLB_LEFTADJ       1
+#define SAMD21_ADC_CTRLB_FREERUN       2
+#define SAMD21_ADC_CTRLB_CORREN                3
+#define SAMD21_ADC_CTRLB_RESSEL                4
+#define  SAMD21_ADC_CTRLB_RESSEL_12BIT         0
+#define  SAMD21_ADC_CTRLB_RESSEL_16BIT         1
+#define  SAMD21_ADC_CTRLB_RESSEL_10BIT         2
+#define  SAMD21_ADC_CTRLB_RESSEL_8BIT          3
+#define SAMD21_ADC_CTRLB_PRESCALER     8
+#define  SAMD21_ADC_CTRLB_PRESCALER_DIV4       0
+#define  SAMD21_ADC_CTRLB_PRESCALER_DIV8       1
+#define  SAMD21_ADC_CTRLB_PRESCALER_DIV16      2
+#define  SAMD21_ADC_CTRLB_PRESCALER_DIV32      3
+#define  SAMD21_ADC_CTRLB_PRESCALER_DIV64      4
+#define  SAMD21_ADC_CTRLB_PRESCALER_DIV128     5
+#define  SAMD21_ADC_CTRLB_PRESCALER_DIV256     6
+#define  SAMD21_ADC_CTRLB_PRESCALER_DIV512     7
+
+#define SAMD21_ADC_SWTRIG_FLUSH                0
+#define SAMD21_ADC_SWTRIG_START                1
+
+#define SAMD21_ADC_INPUTCTRL_MUXPOS            0
+# define SAMD21_ADC_INPUTCTRL_MUXPOS_TEMP              0x18
+# define SAMD21_ADC_INPUTCTRL_MUXPOS_BANDGAP           0x19
+# define SAMD21_ADC_INPUTCTRL_MUXPOS_SCALEDCOREVCC     0x1a
+# define SAMD21_ADC_INPUTCTRL_MUXPOS_SCALEDIOVCC       0x1b
+# define SAMD21_ADC_INPUTCTRL_MUXPOS_DAC               0x1c
+#define SAMD21_ADC_INPUTCTRL_MUXNEG            8
+# define SAMD21_ADC_INPUTCTRL_MUXNEG_GND               0x18
+# define SAMD21_ADC_INPUTCTRL_MUXNEG_IOGND             0x19
+#define SAMD21_ADC_INPUTCTRL_INPUTSCAN         16
+#define SAMD21_ADC_INPUTCTRL_INPUTOFFSET       20
+#define SAMD21_ADC_INPUTCTRL_GAIN              24
+#define  SAMD21_ADC_INPUTCTRL_GAIN_1X                  0
+#define  SAMD21_ADC_INPUTCTRL_GAIN_DIV2                        0xf
+
+#define SAMD21_ADC_INTFLAG_RESRDY      0
+#define SAMD21_ADC_INTFLAG_OVERRUN     1
+#define SAMD21_ADC_INTFLAG_WINMON      2
+#define SAMD21_ADC_INTFLAG_SYNCRDY     3
+
+#define SAMD21_ADC_STATUS_SYNCBUSY     7
+
+#define SAMD21_ADC_CALIB_LINEARITY_CAL 0
+#define SAMD21_ADC_CALIB_BIAS_CAL      16
+
+extern struct samd21_adc samd21_adc;
+
+#define samd21_adc (*(struct samd21_adc *) 0x42004000)
+
+struct samd21_dac {
+       vuint8_t        ctrla;
+       vuint8_t        ctrlb;
+       vuint8_t        evctrl;
+       uint8_t         reserved_03;
+
+       vuint8_t        intenclr;
+       vuint8_t        intenset;
+       vuint8_t        intflag;
+       vuint8_t        status;
+
+       vuint16_t       data;
+       uint16_t        reserved_0a;
+
+       vuint16_t       databuf;
+};
+
+#define SAMD21_DAC_CTRLA_SWRST         0
+#define SAMD21_DAC_CTRLA_ENABLE                1
+#define SAMD21_DAC_CTRLA_RUNSTDBY      2
+
+#define SAMD21_DAC_CTRLB_EOEN          0
+#define SAMD21_DAC_CTRLB_IOEN          1
+#define SAMD21_DAC_CTRLB_LEFTADJ       2
+#define SAMD21_DAC_CTRLB_VPD           3
+#define SAMD21_DAC_CTRLB_BDWP          4
+#define SAMD21_DAC_CTRLB_REFSEL                6
+#define  SAMD21_DAC_CTRLB_REFSEL_INTREF                0
+#define  SAMD21_DAC_CTRLB_REFSEL_VDDANA                1
+#define  SAMD21_DAC_CTRLB_REFSEL_VREFA         2
+#define  SAMD21_DAC_CTRLB_REFSEL_MASK          3
+
+#define SAMD21_DAC_EVCTRL_STARTEI      0
+#define SAMD21_DAC_EVCTRL_EMPTYEO      1
+
+#define SAMD21_DAC_INTENCLR_UNDERRUN   0
+#define SAMD21_DAC_INTENCLR_EMPTY      1
+#define SAMD21_DAC_INTENCLR_SYNCRDY    2
+
+#define SAMD21_DAC_INTENSET_UNDERRUN   0
+#define SAMD21_DAC_INTENSET_EMPTY      1
+#define SAMD21_DAC_INTENSET_SYNCRDY    2
+
+#define SAMD21_DAC_INTFLAG_UNDERRUN    0
+#define SAMD21_DAC_INTFLAG_EMPTY       1
+#define SAMD21_DAC_INTFLAG_SYNCRDY     2
+
+#define SAMD21_DAC_STATUS_SYNCBUSY     7
+
+extern struct samd21_dac samd21_dac;
+#define samd21_dac (*(struct samd21_dac *) 0x42004800)
+
+/* TC */
+struct samd21_tc {
+       vuint16_t       ctrla;
+       vuint16_t       readreq;
+       vuint8_t        ctrlbclr;
+       vuint8_t        ctrlbset;
+       vuint8_t        ctrlc;
+       vuint8_t        reserved_07;
+       vuint8_t        dbgctrl;
+       vuint8_t        reserved_09;
+       vuint16_t       evctrl;
+       vuint8_t        intenclr;
+       vuint8_t        intenset;
+       vuint8_t        intflag;
+       vuint8_t        status;
+
+       union {
+               struct {
+                       vuint8_t        count;
+                       vuint8_t        reserved_11;
+                       vuint16_t       reserved_12;
+                       vuint8_t        per;
+                       vuint8_t        reserved_15;
+                       vuint16_t       reserved_16;
+                       vuint8_t        cc[2];
+               } mode_8;
+               struct {
+                       vuint16_t       count;
+                       vuint16_t       reserved_12;
+                       vuint32_t       reserved_14;
+                       vuint16_t       cc[2];
+               } mode_16;
+               struct {
+                       vuint32_t       count;
+                       vuint32_t       reserved_14;
+                       vuint32_t       cc[2];
+               } mode_32;
+       };
+};
+
+extern struct samd21_tc samd21_tc3;
+#define samd21_tc3 (*(struct samd21_tc *) 0x42002c00)
+
+extern struct samd21_tc samd21_tc4;
+#define samd21_tc4 (*(struct samd21_tc *) 0x42003000)
+
+extern struct samd21_tc samd21_tc5;
+#define samd21_tc5 (*(struct samd21_tc *) 0x42003400)
+
+#ifdef ATSAMD21J
+/* Present on all of the samd21j parts and the samd21g16l */
+extern struct samd21_tc samd21_tc6;
+#define samd21_tc6 (*(struct samd21_tc *) 0x42003800)
+
+extern struct samd21_tc samd21_tc7;
+#define samd21_tc7 (*(struct samd21_tc *) 0x42003c00)
+#endif
+
+#define SAMD21_TC_CTRLA_SWRST          0
+#define SAMD21_TC_CTRLA_ENABLE         1
+#define SAMD21_TC_CTRLA_MODE           2
+#define  SAMD21_TC_CTRLA_MODE_COUNT16          0
+#define  SAMD21_TC_CTRLA_MODE_COUNT8           1
+#define  SAMD21_TC_CTRLA_MODE_COUNT32          2
+#define SAMD21_TC_CTRLA_WAVEGEN                5
+#define  SAMD21_TC_CTRLA_WAVEGEN_NFRQ          0
+#define  SAMD21_TC_CTRLA_WAVEGEN_MFRQ          1
+#define  SAMD21_TC_CTRLA_WAVEGEN_NPWM          2
+#define  SAMD21_TC_CTRLA_WAVEGEN_MPWM          3
+#define SAMD21_TC_CTRLA_PRESCALER      8
+#define  SAMD21_TC_CTRLA_PRESCALER_DIV1                0
+#define  SAMD21_TC_CTRLA_PRESCALER_DIV2                1
+#define  SAMD21_TC_CTRLA_PRESCALER_DIV4                2
+#define  SAMD21_TC_CTRLA_PRESCALER_DIV8                3
+#define  SAMD21_TC_CTRLA_PRESCALER_DIV16       4
+#define  SAMD21_TC_CTRLA_PRESCALER_DIV64       5
+#define  SAMD21_TC_CTRLA_PRESCALER_DIV256      6
+#define  SAMD21_TC_CTRLA_PRESCALER_DIV1024     7
+#define SAMD21_TC_CTRLA_RUNSTDBY       11
+#define SAMD21_TC_CTRLA_PRESCSYNC      12
+#define  SAMD21_TC_CTRLA_PRESCSYNC_GCLK                0
+#define  SAMD21_TC_CTRLA_PRESCSYNC_PRSEC       1
+#define  SAMD21_TC_CTRLA_PRESCSYNC_RESYNC      2
+
+#define SAMD21_TC_READREQ_ADDR         0
+#define SAMD21_TC_READREQ_RCONT                14
+#define SAMD21_TC_READREQ_RREQ         15
+#define SAMD21_TC_CTRLB_DIR            0
+#define SAMD21_TC_CTRLB_ONESHOT                2
+#define SAMD21_TC_CTRLB_CMD            6
+#define SAMD21_TC_CTRLC_INVEN(x)       (0 + (x))
+#define SAMD21_TC_CTRLC_CPTEN(x)       (4 + (x))
+#define SAMD21_TC_DBGCTRL_DBGRUN       0
+#define SAMD21_TC_EVCTRL_EVACT         0
+#define SAMD21_TC_EVCTRL_TCINV         4
+#define SAMD21_TC_EVCTRL_TCEI          5
+#define SAMD21_TC_EVCTRL_OVFEO         8
+#define SAMD21_TC_EVCTRL_MCEO(x)       (12 + (x))
+
+#define SAMD21_TC_INTFLAG_MC(x)                (4 + (x))
+#define SAMD21_TC_INTFLAG_SYNCRDY      3
+#define SAMD21_TC_INTFLAG_ERR          1
+#define SAMD21_TC_INTFLAG_OVF          0
+
+#define SAMD21_TC_STATUS_STOP          3
+#define SAMD21_TC_STATUS_FOLLOWER      4
+#define SAMD21_TC_STATUS_SYNCBUSY      7
+
+/* TCC */
+
+struct samd21_tcc {
+       vuint32_t       ctrla;
+       vuint8_t        ctrlbclr;
+       vuint8_t        ctrlbset;
+       vuint16_t       reserved_06;
+       vuint32_t       syncbusy;
+       vuint32_t       fctrla;
+
+       vuint32_t       fctlrb;
+       vuint32_t       wexctrl;
+       vuint32_t       drvctrl;
+       vuint16_t       reserved_1c;
+       vuint8_t        dbgctrl;
+       vuint8_t        reserved_1f;
+
+       vuint32_t       evctrl;
+       vuint32_t       intenclr;
+       vuint32_t       intenset;
+       vuint32_t       intflag;
+
+       vuint32_t       status;
+       vuint32_t       count;
+       vuint16_t       patt;
+       vuint16_t       reserved_3a;
+       vuint32_t       wave;
+
+       vuint32_t       per;
+       vuint32_t       cc[4];
+       vuint32_t       reserved_54;
+       vuint32_t       reserved_58;
+       vuint32_t       reserved_5c;
+
+       vuint32_t       reserved_60;
+       vuint16_t       pattb;
+       vuint16_t       reserved_66;
+       vuint32_t       waveb;
+       vuint32_t       perb;
+
+       vuint32_t       ccb[4];
+};
+
+extern struct samd21_tcc samd21_tcc0;
+#define samd21_tcc0 (*(struct samd21_tcc *) 0x42002000)
+
+extern struct samd21_tcc samd21_tcc1;
+#define samd21_tcc1 (*(struct samd21_tcc *) 0x42002400)
+
+extern struct samd21_tcc samd21_tcc2;
+#define samd21_tcc2 (*(struct samd21_tcc *) 0x42002800)
+
+#ifdef SAMD21E17D
+/* only on the samd21e17d */
+extern struct samd21_tcc samd21_tcc3;
+#define samd21_tcc3 (*(struct samd21_tcc *) 0x42006000)
+#endif
+
+#define SAMD21_TCC_CTRLA_SWRST         0
+#define SAMD21_TCC_CTRLA_ENABLE                1
+#define SAMD21_TCC_CTRLA_RESOLUTION    5
+#define  SAMD21_TCC_CTRLA_RESOLUTION_NONE      0
+#define  SAMD21_TCC_CTRLA_RESOLUTION_DITH4     1
+#define  SAMD21_TCC_CTRLA_RESOLUTION_DITH5     2
+#define  SAMD21_TCC_CTRLA_RESOLUTION_DITH6     3
+#define SAMD21_TCC_CTRLA_PRESCALER     8
+#define  SAMD21_TCC_CTRLA_PRESCALER_DIV1       0
+#define  SAMD21_TCC_CTRLA_PRESCALER_DIV2       1
+#define  SAMD21_TCC_CTRLA_PRESCALER_DIV4       2
+#define  SAMD21_TCC_CTRLA_PRESCALER_DIV8       3
+#define  SAMD21_TCC_CTRLA_PRESCALER_DIV16      4
+#define  SAMD21_TCC_CTRLA_PRESCALER_DIV64      5
+#define  SAMD21_TCC_CTRLA_PRESCALER_DIV256     6
+#define  SAMD21_TCC_CTRLA_PRESCALER_DIV1024    7
+#define SAMD21_TCC_CTRLA_RUNSTDBY      11
+#define SAMD21_TCC_CTRLA_PRESYNC       12
+#define  SAMD21_TCC_CTRLA_PRESYNC_GCLK         0
+#define  SAMD21_TCC_CTRLA_PRESYNC_PRESC                1
+#define  SAMD21_TCC_CTRLA_PRESYNC_RESYNC       2
+#define SAMD21_TCC_CTRLA_ALOCK         14
+#define SAMD21_TCC_CTRLA_CPTEN(n)      (24 + (n))
+
+#define SAMD21_TCC_CTRLB_DIR           0
+#define SAMD21_TCC_CTRLB_LUPD          1
+#define SAMD21_TCC_CTRLB_ONESHOT       2
+#define SAMD21_TCC_CTRLB_IDXCMD                3
+#define  SAMD21_TCC_CTRLB_IDXCMD_DISABLE       0
+#define  SAMD21_TCC_CTRLB_IDXCMD_SET           1
+#define  SAMD21_TCC_CTRLB_IDXCMD_CLEAR         2
+#define  SAMD21_TCC_CTRLB_IDXCMD_HOLD          3
+#define SAMD21_TCC_CTRLB_CMD           5
+#define  SAMD21_TCC_CTRLB_CMD_NONE             0
+#define  SAMD21_TCC_CTRLB_CMD_RETRIGGER                1
+#define  SAMD21_TCC_CTRLB_CMD_STOP             2
+#define  SAMD21_TCC_CTRLB_CMD_UPDATE           3
+#define  SAMD21_TCC_CTRLB_CMD_READSYNC         4
+#define  SAMD21_TCC_CTRLB_CMD_DMAOS            5
+
+#define SAMD21_TCC_SYNCBUSY_SWRST      0
+#define SAMD21_TCC_SYNCBUSY_ENABLE     1
+#define SAMD21_TCC_SYNCBUSY_CTRLB      2
+#define SAMD21_TCC_SYNCBUSY_STATUS     3
+#define SAMD21_TCC_SYNCBUSY_COUNT      4
+#define SAMD21_TCC_SYNCBUSY_PATT       5
+#define SAMD21_TCC_SYNCBUSY_WAVE       6
+#define SAMD21_TCC_SYNCBUSY_PER                7
+#define SAMD21_TCC_SYNCBUSY_CC(x)      (8 + (x))
+#define SAMD21_TCC_SYNCBUSY_PATTB      16
+#define SAMD21_TCC_SYNCBUSY_WAVEB      17
+#define SAMD21_TCC_SYNCBUSY_PERB       18
+#define SAMD21_TCC_SYNCBUSY_CCB(x)     ((19 + (x))
+
+#define SAMD21_TCC_DBGCTRL_FDDBD       2
+#define SAMD21_TCC_DBGCTRL_DBGRUN      0
+
+#define SAMD21_TCC_EVCTRL_EVACTO       0
+#define SAMD21_TCC_EVCTRL_EVACT1       3
+#define SAMD21_TCC_EVCTRL_CNTSEL       6
+#define SAMD21_TCC_EVCTRL_OVFEO                8
+#define SAMD21_TCC_EVCTRL_TRGEO                9
+#define SAMD21_TCC_EVCTRL_CNTEO                10
+#define SAMD21_TCC_EVCTRL_TCINV(x)     (12 + (x))
+#define SAMD21_TCC_EVCTRL_MCEI(x)      (16 + (x))
+#define SAMD21_TCC_EVCTRL_MCEO(x)      (24 + (x))
+
+#define SAMD21_TCC_INTFLAG_OVF         0
+#define SAMD21_TCC_INTFLAG_TRG         1
+#define SAMD21_TCC_INTFLAG_CNT         2
+#define SAMD21_TCC_INTFLAG_ERR         3
+#define SAMD21_TCC_INTFLAG_UFS         10
+#define SAMD21_TCC_INTFLAG_DFS         11
+#define SAMD21_TCC_INTFLAG_FAULTA      12
+#define SAMD21_TCC_INTFLAG_FAULTB      13
+#define SAMD21_TCC_INTFLAG_FAULT0      14
+#define SAMD21_TCC_INTFLAG_FAULT1      15
+#define SAMD21_TCC_INTFLAG_MC(x)       (16 + (x))
+
+#define SAMD21_TCC_WAVE_WAVEGEN                0
+#define  SAMD21_TCC_WAVE_WAVEGEN_NFRQ          0
+#define  SAMD21_TCC_WAVE_WAVEGEN_MFRQ          1
+#define  SAMD21_TCC_WAVE_WAVEGEN_NPWM          2
+#define  SAMD21_TCC_WAVE_WAVEGEN_DSCRITICAL    4
+#define  SAMD21_TCC_WAVE_WAVEGEN_DSBOTTOM      5
+#define  SAMD21_TCC_WAVE_WAVEGEN_DSBOTH                6
+#define  SAMD21_TCC_WAVE_WAVEGEN_DSTOP         7
+#define SAMD21_TCC_WAVE_RAMP           4
+#define SAMD21_TCC_WAVE_CIPEREN                7
+#define SAMD21_TCC_WAVE_CCCEN(x)       (8 + (x))
+#define SAMD21_TCC_WAVE_POL(x)         (16 + (x))
+#define SAMD21_TCC_WAVE_SWAP(x)                (24 + (x))
+
+/* USB */
+
+struct samd21_usb {
+       vuint8_t        ctrla;
+       vuint8_t        reserved_01;
+       vuint8_t        syncbusy;
+       vuint8_t        qosctrl;
+
+       vuint32_t       reserved_04;
+       vuint16_t       ctrlb;
+       vuint8_t        dadd;
+       vuint8_t        reserved_0b;
+       vuint8_t        status;
+       vuint8_t        fsmstatus;
+       vuint16_t       reserved_0e;
+
+       vuint16_t       fnum;
+       vuint16_t       reserved_12;
+       vuint16_t       intenclr;
+       vuint16_t       reserved_16;
+       vuint16_t       intenset;
+       vuint16_t       reserved_1a;
+       vuint16_t       intflag;
+       vuint16_t       reserved_1e;
+
+       vuint16_t       epintsmry;
+       vuint16_t       reserved_22;
+
+       vuint32_t       descadd;
+       vuint16_t       padcal;
+       uint8_t         reserved_2a[0x100 - 0x2a];
+
+       struct {
+               vuint8_t        epcfg;
+               vuint8_t        reserved_01;
+               vuint8_t        reserved_02;
+               vuint8_t        binterval;
+               vuint8_t        epstatusclr;
+               vuint8_t        epstatusset;
+               vuint8_t        epstatus;
+               vuint8_t        epintflag;
+               vuint8_t        epintenclr;
+               vuint8_t        epintenset;
+               vuint8_t        reserved_0a[0x20 - 0x0a];
+       } ep[8];
+};
+
+extern struct samd21_usb samd21_usb;
+
+#define samd21_usb (*(struct samd21_usb *) 0x41005000)
+
+#define SAMD21_USB_CTRLA_SWRST         0
+#define SAMD21_USB_CTRLA_ENABLE                1
+#define SAMD21_USB_CTRLA_RUNSTDBY      2
+#define SAMD21_USB_CTRLA_MODE          7
+
+#define SAMD21_USB_SYNCBUSY_SWRST      0
+#define SAMD21_USB_SYNCBUSY_ENABLE     1
+
+#define SAMD21_USB_QOSCTRL_CQOS                0
+#define SAMD21_USB_QOSCTRL_DQOS                2
+
+#define SAMD21_USB_CTRLB_DETACH                0
+#define SAMD21_USB_CTRLB_UPRSM         1
+#define SAMD21_USB_CTRLB_SPDCONF       2
+#define  SAMD21_USB_CTRLB_SPDCONF_FS           0
+#define  SAMD21_USB_CTRLB_SPDCONF_LS           1
+#define  SAMD21_USB_CTRLB_SPDCONF_MASK         0x3
+#define SAMD21_USB_CTRLB_NREPLY                4
+#define SAMD21_USB_CTRLB_GNAK          9
+#define SAMD21_USB_CTRLB_LPMHDSK       10
+#define  SAMD21_USB_CTRLB_LPMHDSK_NONE         0
+#define  SAMD21_USB_CTRLB_LPMHDSK_ACK          1
+#define  SAMD21_USB_CTRLB_LPMHDSK_NYET         2
+#define  SAMD21_USB_CTRLB_LPMHDSK_MASK         3
+
+#define SAMD21_USB_DADD_DADD           0
+#define SAMD21_USB_DADD_ADDEN          7
+
+#define SAMD21_USB_STATUS_SPEED                2
+#define SAMD21_USB_STATUS_LINESTATE    6
+#define SAMD21_USB_FNUM_MFNUM          0
+#define SAMD21_USB_FNUM_FNUM           3
+#define SAMD21_USB_FNUM_FNCERR         15
+#define SAMD21_USB_INTFLAG_SUSPEND     0
+#define SAMD21_USB_INTFLAG_SOF         2
+#define SAMD21_USB_INTFLAG_EORST       3
+#define SAMD21_USB_INTFLAG_WAKEUP      4
+#define SAMD21_USB_INTFLAG_EORSM       5
+#define SAMD21_USB_INTFLAG_UPRSM       6
+#define SAMD21_USB_INTFLAG_RAMACER     7
+#define SAMD21_USB_INTFLAG_LPMNYET     8
+#define SAMD21_USB_INTFLAG_LPMSUSP     9
+
+#define SAMD21_USB_PADCAL_TRANSP       0
+#define SAMD21_USB_PADCAL_TRANSN       6
+#define SAMD21_USB_PADCAL_TRIM         12
+
+#define SAMD21_USB_EP_EPCFG_EP_TYPE_OUT                0
+#define  SAMD21_USB_EP_EPCFG_EP_TYPE_OUT_DISABLED      0
+#define  SAMD21_USB_EP_EPCFG_EP_TYPE_OUT_CONTROL       1
+#define  SAMD21_USB_EP_EPCFG_EP_TYPE_OUT_ISOCHRONOUS   2
+#define  SAMD21_USB_EP_EPCFG_EP_TYPE_OUT_BULK          3
+#define  SAMD21_USB_EP_EPCFG_EP_TYPE_OUT_INTERRUPT     4
+#define  SAMD21_USB_EP_EPCFG_EP_TYPE_OUT_DUAL_BANK     5
+#define SAMD21_USB_EP_EPCFG_EP_TYPE_IN         4
+#define  SAMD21_USB_EP_EPCFG_EP_TYPE_IN_DISABLED       0
+#define  SAMD21_USB_EP_EPCFG_EP_TYPE_IN_CONTROL        1
+#define  SAMD21_USB_EP_EPCFG_EP_TYPE_IN_ISOCHRONOUS    2
+#define  SAMD21_USB_EP_EPCFG_EP_TYPE_IN_BULK           3
+#define  SAMD21_USB_EP_EPCFG_EP_TYPE_IN_INTERRUPT      4
+#define  SAMD21_USB_EP_EPCFG_EP_TYPE_IN_DUAL_BANK      5
+
+#define SAMD21_USB_EP_EPSTATUS_DTGLOUT                 0
+#define SAMD21_USB_EP_EPSTATUS_DTGLIN                  1
+#define SAMD21_USB_EP_EPSTATUS_CURBK                   2
+#define SAMD21_USB_EP_EPSTATUS_STALLRQ0                        4
+#define SAMD21_USB_EP_EPSTATUS_STALLRQ1                        5
+#define SAMD21_USB_EP_EPSTATUS_BK0RDY                  6
+#define SAMD21_USB_EP_EPSTATUS_BK1RDY                  7
+
+#define SAMD21_USB_EP_EPINTFLAG_TRCPT0                 0
+#define SAMD21_USB_EP_EPINTFLAG_TRCPT1                 1
+#define SAMD21_USB_EP_EPINTFLAG_TRFAIL0                        2
+#define SAMD21_USB_EP_EPINTFLAG_TRFAIL1                        3
+#define SAMD21_USB_EP_EPINTFLAG_RXSTP                  4
+#define SAMD21_USB_EP_EPINTFLAG_STALL                  5
+
+struct samd21_usb_desc_bank {
+       vuint32_t       addr;
+       vuint32_t       pcksize;
+       vuint16_t       extreg;
+       vuint8_t        status_bk;
+       vuint8_t        reserved_0b;
+       vuint32_t       reserved_0c;
+};
+
+struct samd21_usb_desc {
+       struct samd21_usb_desc_bank bank[2];
+};
+
+extern struct samd21_usb_desc  samd21_usb_desc[8];
+
+#define SAMD21_USB_DESC_PCKSIZE_BYTE_COUNT             0
+#define  SAMD21_USB_DESC_PCKSIZE_BYTE_COUNT_MASK               0x3fffU
+#define SAMD21_USB_DESC_PCKSIZE_MULTI_PACKET_SIZE      14
+#define  SAMD21_USB_DESC_PCKSIZE_MULTI_PACKET_SIZE_MASK                0x3fffU
+#define SAMD21_USB_DESC_PCKSIZE_SIZE                   28
+#define  SAMD21_USB_DESC_PCKSIZE_SIZE_8                                0
+#define  SAMD21_USB_DESC_PCKSIZE_SIZE_16                       1
+#define  SAMD21_USB_DESC_PCKSIZE_SIZE_32                       2
+#define  SAMD21_USB_DESC_PCKSIZE_SIZE_64                       3
+#define  SAMD21_USB_DESC_PCKSIZE_SIZE_128                      4
+#define  SAMD21_USB_DESC_PCKSIZE_SIZE_256                      5
+#define  SAMD21_USB_DESC_PCKSIZE_SIZE_512                      6
+#define  SAMD21_USB_DESC_PCKSIZE_SIZE_1023                     7
+#define  SAMD21_USB_DESC_PCKSIZE_SIZE_MASK                     7U
+#define SAMD21_USB_DESC_PCKSIZE_AUTO_ZLP               31
+
+static inline uint16_t
+samd21_usb_desc_get_byte_count(uint8_t ep, uint8_t bank)
+{
+       return ((samd21_usb_desc[ep].bank[bank].pcksize >> SAMD21_USB_DESC_PCKSIZE_BYTE_COUNT) &
+               SAMD21_USB_DESC_PCKSIZE_BYTE_COUNT_MASK);
+}
+
+static inline void
+samd21_usb_desc_set_byte_count(uint8_t ep, uint8_t bank, uint32_t count)
+{
+       uint32_t pcksize = samd21_usb_desc[ep].bank[bank].pcksize;
+
+       pcksize &= ~(SAMD21_USB_DESC_PCKSIZE_BYTE_COUNT_MASK << SAMD21_USB_DESC_PCKSIZE_BYTE_COUNT);
+       pcksize &= ~(SAMD21_USB_DESC_PCKSIZE_MULTI_PACKET_SIZE_MASK << SAMD21_USB_DESC_PCKSIZE_MULTI_PACKET_SIZE);
+       pcksize |= (count << SAMD21_USB_DESC_PCKSIZE_BYTE_COUNT);
+       samd21_usb_desc[ep].bank[bank].pcksize = pcksize;
+}
+
+static inline void
+samd21_usb_desc_set_size(uint8_t ep, uint8_t bank, uint32_t size)
+{
+       uint32_t pcksize = samd21_usb_desc[ep].bank[bank].pcksize;
+
+       pcksize &= ~(SAMD21_USB_DESC_PCKSIZE_SIZE_MASK << SAMD21_USB_DESC_PCKSIZE_SIZE);
+
+       uint32_t size_bits = 0;
+       switch (size) {
+       case 8: size_bits = SAMD21_USB_DESC_PCKSIZE_SIZE_8; break;
+       case 16: size_bits = SAMD21_USB_DESC_PCKSIZE_SIZE_16; break;
+       case 32: size_bits = SAMD21_USB_DESC_PCKSIZE_SIZE_32; break;
+       case 64: size_bits = SAMD21_USB_DESC_PCKSIZE_SIZE_64; break;
+       case 128: size_bits = SAMD21_USB_DESC_PCKSIZE_SIZE_128; break;
+       case 256: size_bits = SAMD21_USB_DESC_PCKSIZE_SIZE_256; break;
+       case 512: size_bits = SAMD21_USB_DESC_PCKSIZE_SIZE_512; break;
+       case 1023: size_bits = SAMD21_USB_DESC_PCKSIZE_SIZE_1023; break;
+       }
+       pcksize |= (size_bits << SAMD21_USB_DESC_PCKSIZE_SIZE);
+       samd21_usb_desc[ep].bank[bank].pcksize = pcksize;
+}
+
+static inline void
+samd21_usb_ep_set_ready(uint8_t ep, uint8_t bank)
+{
+       samd21_usb.ep[ep].epstatusset = (1 << (SAMD21_USB_EP_EPSTATUS_BK0RDY + bank));
+       samd21_usb.ep[ep].epintflag = (1 << (SAMD21_USB_EP_EPINTFLAG_TRFAIL0 + bank));
+}
+
+static inline void
+samd21_usb_ep_clr_ready(uint8_t ep, uint8_t bank)
+{
+       samd21_usb.ep[ep].epstatusclr = (1 << (SAMD21_USB_EP_EPSTATUS_BK0RDY + bank));
+}
+
+static inline uint8_t
+samd21_usb_ep_ready(uint8_t ep)
+{
+       return (samd21_usb.ep[ep].epstatus >> SAMD21_USB_EP_EPSTATUS_BK0RDY) & 3;
+}
+
+static inline uint8_t
+samd21_usb_ep_curbk(uint8_t ep)
+{
+       return (samd21_usb.ep[ep].epstatus >> SAMD21_USB_EP_EPSTATUS_CURBK) & 1;
+}
+
+/* evsys */
+
+struct samd21_evsys {
+       vuint8_t        ctrl;
+       vuint8_t        reserved_01;
+       vuint16_t       reserved_02;
+       vuint32_t       channel;
+       vuint16_t       user;
+       vuint16_t       reserved_0a;
+       vuint32_t       chstatus;
+
+       vuint32_t       intenclr;
+       vuint32_t       intenset;
+       vuint32_t       intflag;
+};
+
+extern struct samd21_evsys samd21_evsys;
+
+#define SAMD21_NUM_EVSYS       16
+
+#define samd21_evsys   (*(struct samd21_evsys *) 0x42000400)
+
+#define SAMD21_EVSYS_CONTROL_SWRST     0
+#define SAMD21_EVSYS_CONTROL_GCLKREQ   4
+
+#define SAMD21_EVSYS_CHANNEL_CHANNEL   0
+
+#define SAMD21_EVSYS_CHANNEL_SWEVT     8
+
+#define SAMD21_EVSYS_CHANNEL_EVGEN     16
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_NONE               0x00
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_RTC_CMP(i)         (0x01 + (i))
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_OVF                        0x03
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_PER(i)             (0x04 + (i))
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_EXTINT(i)          (0x0c + (i))
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_DMAC_CH(i)         (0x1e + (i))
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC0_OVF           0x22
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC0_TRG           0x23
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC0_CNT           0x29
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC0_MCX(i)                (0x25 + (i))
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC1_OVF           0x29
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC1_TRG           0x2a
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC1_CNT           0x2b
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC1_MCX(i)                (0x2c + (i))
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC2_OVF           0x2e
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC2_TRG           0x2f
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC2_CNT           0x30
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC2_MCX(i)                (0x31 + (i))
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TC3_OVF            0x33
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TC3_MC(i)          (0x34 + (i))
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TC4_OVF            0x36
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TC4_MC(i)          (0x37 + (i))
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TC5_OVF            0x39
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TC5_MC(i)          (0x3a + (i))
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TC6_OVF            0x3c
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TC6_MC(i)          (0x3d + (i))
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TC7_OVF            0x3f
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TC7_MC(i)          (0x40 + (i))
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_ADC_RESRDY         0x42
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_ADC_WINMON         0x43
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_AC_COMP0           0x44
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_AC_COMP1           0x45
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_AC_WIN0            0x46
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_DAC_EMPTY          0x47
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_PTC_EOC            0x48
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_PTC_WCOMP          0x49
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_AC_COMP2           0x4a
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_AC_COMP3           0x4b
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_AC_WIN1            0x4c
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC3_OVF           0x4d
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC3_TRG           0x4e
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC3_CNT           0x4f
+#define  SAMD21_EVSYS_CHANNEL_EVGEN_TCC3_MCX(i)                (0x50 + (i))
+
+#define SAMD21_EVSYS_CHANNEL_PATH      24
+#define  SAMD21_EVSYS_CHANNEL_PATH_SYNCHRONOUS         0
+#define  SAMD21_EVSYS_CHANNEL_PATH_RESYNCHRONIZED      1
+#define  SAMD21_EVSYS_CHANNEL_PATH_ASYNCHRONOUS                2
+
+#define SAMD21_EVSYS_CHANNEL_EDGESEL   26
+#define  SAMD21_EVSYS_CHANNEL_EDGESEL_NO_EVT_OUTPUT    0
+#define  SAMD21_EVSYS_CHANNEL_EDGESEL_RISING_EDGE      1
+#define  SAMD21_EVSYS_CHANNEL_EDGESEL_FALLING_EDGE     2
+#define  SAMD21_EVSYS_CHANNEL_EDGESEL_BOTH_EDGES       3
+
+#define SAMD21_EVSYS_USER_USER         0
+#define  SAMD21_EVSYS_USER_USER_DMAC_CH(n)     (0x00 + (n))
+#define  SAMD21_EVSYS_USER_USER_TCC0_EV(n)     (0x04 + (n))
+#define  SAMD21_EVSYS_USER_USER_TCC0_MC(n)     (0x06 + (n))
+#define  SAMD21_EVSYS_USER_USER_TCC1_EV(n)     (0x0a + (n))
+#define  SAMD21_EVSYS_USER_USER_TCC1_MC(n)     (0x0c + (n))
+#define  SAMD21_EVSYS_USER_USER_TCC2_EV(n)     (0x0e + (n))
+#define  SAMD21_EVSYS_USER_USER_TCC2_MC(n)     (0x10 + (n))
+#define  SAMD21_EVSYS_USER_USER_TC(n)          (0x12 + (n))
+#define  SAMD21_EVSYS_USER_USER_ADC_START      (0x17)
+#define  SAMD21_EVSYS_USER_USER_ADC_SYNC       0x18
+#define  SAMD21_EVSYS_USER_USER_AC_COMP0       0x19
+#define  SAMD21_EVSYS_USER_USER_AC_COMP1       0x1a
+#define  SAMD21_EVSYS_USER_USER_DAC_START      0x1b
+#define  SAMD21_EVSYS_USER_USER_PTC_STCONV     0x1c
+#define  SAMD21_EVSYS_USER_USER_AC_COMP2       0x1d
+#define  SAMD21_EVSYS_USER_USER_AC_COMP3       0x1e
+#define  SAMD21_EVSYS_USER_USER_TCC3_EV(n)     (0x1f + (n))
+#define  SAMD21_EVSYS_USER_USER_TCC3_MC(n)     (0x21 + (n))
+
+#define SAMD21_EVSYS_USER_CHANNEL      8
+#define  SAMD21_EVSYS_USER_CHANNEL_NONE                0
+#define  SAMD21_EVSYS_USER_CHANNEL_NUM(n)      ((n) + 1)
+
+
+#define SAMD21_EVSYS_CHSTATUS_USRRDY(n)        (((n) & 7) | (((n) & 8) << 1))
+#define SAMD21_EVSYS_CHSTATUS_CHBUSY(n)        (((n) & 7) | (((n) & 8) << 1) | 8)
+
+/* sercom */
+
+struct samd21_sercom {
+       vuint32_t       ctrla;
+       vuint32_t       ctrlb;
+       vuint32_t       reserved_08;
+       vuint16_t       baud;
+       vuint8_t        rxpl;
+       vuint8_t        reserved_0f;
+
+       vuint32_t       reserved_10;
+       vuint8_t        intenclr;
+       vuint8_t        reserved_15;
+       vuint8_t        intenset;
+       vuint8_t        reserved_17;
+       vuint8_t        intflag;
+       vuint8_t        reserved_19;
+       vuint16_t       status;
+       vuint32_t       syncbusy;
+
+       vuint32_t       reserved_20;
+       vuint32_t       addr;
+       vuint16_t       data;
+       vuint16_t       reserved_2a;
+       vuint32_t       reserved_2c;
+
+       vuint8_t        dbgctrl;
+       vuint8_t        reserved_31;
+       vuint16_t       reserved_32;
+       vuint16_t       fifospace;
+       vuint16_t       fifoptr;
+};
+
+extern struct samd21_sercom samd21_sercom0;
+extern struct samd21_sercom samd21_sercom1;
+extern struct samd21_sercom samd21_sercom2;
+extern struct samd21_sercom samd21_sercom3;
+extern struct samd21_sercom samd21_sercom4;
+extern struct samd21_sercom samd21_sercom5;
+
+#define SAMD21_NUM_SERCOM      6
+
+#define samd21_sercom0 (*(struct samd21_sercom *) 0x42000800)
+#define samd21_sercom1 (*(struct samd21_sercom *) 0x42000c00)
+#define samd21_sercom2 (*(struct samd21_sercom *) 0x42001000)
+#define samd21_sercom3 (*(struct samd21_sercom *) 0x42001400)
+#define samd21_sercom4 (*(struct samd21_sercom *) 0x42001800)
+#define samd21_sercom5 (*(struct samd21_sercom *) 0x42001c00)
+
+#define SAMD21_SERCOM_CTRLA_SWRST      0
+#define SAMD21_SERCOM_CTRLA_ENABLE     1
+#define SAMD21_SERCOM_CTRLA_MODE       2
+# define SAMD21_SERCOM_CTRLA_MODE_USART                1
+# define SAMD21_SERCOM_CTRLA_MODE_SPI_CLIENT   2
+# define SAMD21_SERCOM_CTRLA_MODE_SPI_HOST     3
+# define SAMD21_SERCOM_CTRLA_MODE_I2C_CLIENT   4
+# define SAMD21_SERCOM_CTRLA_MODE_I2C_HOST     5
+
+#define SAMD21_SERCOM_CTRLA_RUNSTDBY   7
+
+/* USART mode */
+#define SAMD21_SERCOM_CTRLA_IBON       8
+#define SAMD21_SERCOM_CTRLA_SAMPR      13
+#define SAMD21_SERCOM_CTRLA_TXPO       16
+#define  SAMD21_SERCOM_CTRLA_TXPO_TX_0                 0
+#define  SAMD21_SERCOM_CTRLA_TXPO_TX_2                 1
+#define  SAMD21_SERCOM_CTRLA_TXPO_TX_0_RTS_2_CTS_3     2
+#define SAMD21_SERCOM_CTRLA_RXPO       20
+#define  SAMD21_SERCOM_CTRLA_RXPO_RX_0                 0
+#define  SAMD21_SERCOM_CTRLA_RXPO_RX_1                 1
+#define  SAMD21_SERCOM_CTRLA_RXPO_RX_2                 2
+#define  SAMD21_SERCOM_CTRLA_RXPO_RX_3                 3
+#define SAMD21_SERCOM_CTRLA_SAMPA      22
+#define SAMD21_SERCOM_CTRLA_FORM       24
+#define SAMD21_SERCOM_CTRLA_CMODE      28
+#define SAMD21_SERCOM_CTRLA_CPOL       29
+#define SAMD21_SERCOM_CTRLA_DORD       30
+
+/* I2C controller mode */
+#define SAMD21_SERCOM_CTRLA_PINOUT     16
+#define SAMD21_SERCOM_CTRLA_SDAHOLD    20
+#define  SAMD21_SERCOM_CTRLA_SDAHOLD_DIS       0
+#define  SAMD21_SERCOM_CTRLA_SDAHOLD_75NS      1
+#define  SAMD21_SERCOM_CTRLA_SDAHOLD_450NS     2
+#define  SAMD21_SERCOM_CTRLA_SDAHOLD_600NS     3
+#define SAMD21_SERCOM_CTRLA_MEXTTOEN   22
+#define SAMD21_SERCOM_CTRLA_SEXTTOEN   23
+#define SAMD21_SERCOM_CTRLA_SPEED      24
+#define  SAMD21_SERCOM_CTRLA_SPEED_STANDARD    0
+#define  SAMD21_SERCOM_CTRLA_SPEED_FAST                1
+#define  SAMD21_SERCOM_CTRLA_SPEED_HIGH                2
+#define SAMD21_SERCOM_CTRLA_SCLSM      27
+#define SAMD21_SERCOM_CTRLA_INACTOUT   28
+#define  SAMD21_SERCOM_CTRLA_INACTOUT_DIS      0
+#define  SAMD21_SERCOM_CTRLA_INACTOUT_55US     1
+#define  SAMD21_SERCOM_CTRLA_INACTOUT_105US    2
+#define  SAMD21_SERCOM_CTRLA_INACTOUT_205US    3
+#define SAMD21_SERCOM_CTRLA_LOWTOUT    30
+
+/* SPI controller mode */
+#define SAMD21_SERCOM_CTRLA_DOPO       16
+#define  SAMD21_SERCOM_CTRLA_DOPO_MOSI_0_SCLK_1        0UL
+#define  SAMD21_SERCOM_CTRLA_DOPO_MOSI_2_SCLK_3        1UL
+#define  SAMD21_SERCOM_CTRLA_DOPO_MOSI_3_SCLK_1        2UL
+#define  SAMD21_SERCOM_CTRLA_DOPO_MOSI_0_SCLK_3        3UL
+#define  SAMD21_SERCOM_CTRLA_DOPO_MASK         3UL
+
+#define SAMD21_SERCOM_CTRLA_DIPO       20
+#define  SAMD21_SERCOM_CTRLA_DIPO_MISO_0       0UL
+#define  SAMD21_SERCOM_CTRLA_DIPO_MISO_1       1UL
+#define  SAMD21_SERCOM_CTRLA_DIPO_MISO_2       2UL
+#define  SAMD21_SERCOM_CTRLA_DIPO_MISO_3       3UL
+#define  SAMD21_SERCOM_CTRLA_DIPO_MASK         3UL
+
+#define SAMD21_SERCOM_CTRLA_FORM       24
+#define SAMD21_SERCOM_CTRLA_CPHA       28
+#define SAMD21_SERCOM_CTRLA_CPOL       29
+#define SAMD21_SERCOM_CTRLA_DORD       30
+#define  SAMD21_SERCOM_CTRLA_DORD_LSB  1
+#define  SAMD21_SERCOM_CTRLA_DORD_MSB  0
+
+/* USART mode */
+#define SAMD21_SERCOM_CTRLB_CHSIZE     0
+#define SAMD21_SERCOM_CTRLB_SBMODE     6
+#define SAMD21_SERCOM_CTRLB_COLDEN     8
+#define SAMD21_SERCOM_CTRLB_SFDE       9
+#define SAMD21_SERCOM_CTRLB_ENC                10
+#define SAMD21_SERCOM_CTRLB_PMODE      13
+#define SAMD21_SERCOM_CTRLB_TXEN       16
+#define SAMD21_SERCOM_CTRLB_RXEN       17
+#define SAMD21_SERCOM_CTRLB_FIFOCLR    22
+
+/* I2C mode */
+#define SAMD21_SERCOM_CTRLB_SMEN       8
+#define SAMD21_SERCOM_CTRLB_QCEN       9
+#define SAMD21_SERCOM_CTRLB_CMD                16
+#define  SAMD21_SERCOM_CTRLB_CMD_NOP           0
+#define  SAMD21_SERCOM_CTRLB_CMD_START         1
+#define  SAMD21_SERCOM_CTRLB_CMD_READ          2
+#define  SAMD21_SERCOM_CTRLB_CMD_STOP          3
+#define SAMD21_SERCOM_CTRLB_ACKACT     18
+#define  SAMD21_SERCOM_CTRLB_ACKACT_ACK                0
+#define  SAMD21_SERCOM_CTRLB_ACKACT_NACK       1
+#define SAMD21_SERCOM_CTRLB_FIFOCLR    22
+
+/* SPI mode */
+#define SAMD21_SERCOM_CTRLB_CHSIZE     0
+# define SAMD21_SERCOM_CTRLB_CHSIZE_8          0
+#define SAMD21_SERCOM_CTRLB_PLOADEN    6
+#define SAMD21_SERCOM_CTRLB_SSDE       9
+#define SAMD21_SERCOM_CTRLB_MSSEN      13
+#define SAMD21_SERCOM_CTRLB_AMODE      14
+#define SAMD21_SERCOM_CTRLB_RXEN       17
+
+/* USART mode */
+#define SAMD21_SERCOM_INTFLAG_DRE      0
+#define SAMD21_SERCOM_INTFLAG_TXC      1
+#define SAMD21_SERCOM_INTFLAG_RXC      2
+#define SAMD21_SERCOM_INTFLAG_RXS      3
+#define SAMD21_SERCOM_INTFLAG_CTSIC    4
+#define SAMD21_SERCOM_INTFLAG_RXBRK    5
+#define SAMD21_SERCOM_INTFLAG_ERROR    7
+
+/* I2C mode */
+#define SAMD21_SERCOM_INTFLAG_ERROR    7
+#define SAMD21_SERCOM_INTFLAG_RXFF     4
+#define SAMD21_SERCOM_INTFLAG_TXFE     3
+#define SAMD21_SERCOM_INTFLAG_SB       1
+#define SAMD21_SERCOM_INTFLAG_MB       0
+
+/* SPI mode */
+#define SAMD21_SERCOM_INTFLAG_SSL      3
+
+#define SAMD21_SERCOM_INTENCLR_DRE     0
+#define SAMD21_SERCOM_INTENCLR_TXC     1
+#define SAMD21_SERCOM_INTENCLR_RXC     2
+#define SAMD21_SERCOM_INTENCLR_RXS     3
+#define SAMD21_SERCOM_INTENCLR_CTSIC   4
+#define SAMD21_SERCOM_INTENCLR_RXBRK   5
+#define SAMD21_SERCOM_INTENCLR_ERROR   7
+
+#define SAMD21_SERCOM_STATUS_PERR      0
+#define SAMD21_SERCOM_STATUS_FERR      1
+#define SAMD21_SERCOM_STATUS_BUFOVF    2
+#define SAMD21_SERCOM_STATUS_CTS       3
+#define SAMD21_SERCOM_STATUS_ISF       4
+#define SAMD21_SERCOM_STATUS_COLL      5
+#define SAMD21_SERCOM_STATUS_TXE       6
+
+#define SAMD21_SERCOM_SYNCBUSY_SWRST   0
+#define SAMD21_SERCOM_SYNCBUSY_ENABLE  1
+#define SAMD21_SERCOM_SYNCBUSY_CTRLB   2
+#define SAMD21_SERCOM_SYNCBUSY_SYSOP   2
+
+#define SAMD21_SERCOM_ADDR_ADDR                0
+#define SAMD21_SERCOM_ADDR_LENEN       13
+#define SAMD21_SERCOM_ADDR_HS          14
+#define SAMD21_SERCOM_ADDR_TENBITEN    15
+#define SAMD21_SERCOM_ADDR_LEN         16
+
+#define SAMD21_SERCOM_DBGCTRL_DBGSTOP  0
+
+#define SAMD21_SERCOM_FIFOSPACE_TXSPACE        0
+#define  SAMD21_SERCOM_FIFOSPACE_TXSPACE_MASK  0x1f
+#define SAMD21_SERCOM_FIFOSPACE_RXSPACE        8
+#define  SAMD21_SERCOM_FIFOSPACE_RXSPACE_MASK  0x1f
+
+#define SAMD21_SERCOM_FIFOPTR_CPUWRPTR 0
+#define  SAMD21_SERCOM_FIFOPTR_CPUWRPTR_MASK   0xf
+#define SAMD21_SERCOM_FIFOPTR_CPURDPTR 8
+#define  SAMD21_SERCOM_FIFOPTR_CPURDPTR_MASK   0xf
+
+/* The SYSTICK starts at 0xe000e010 */
+struct samd21_systick {
+       vuint32_t       csr;
+       vuint32_t       rvr;
+       vuint32_t       cvr;
+       vuint32_t       calib;
+};
+
+extern struct samd21_systick samd21_systick;
+
+#define samd21_systick (*(struct samd21_systick *) 0xe000e010)
+
+#define SAMD21_SYSTICK_CSR_ENABLE      0
+#define SAMD21_SYSTICK_CSR_TICKINT     1
+#define SAMD21_SYSTICK_CSR_CLKSOURCE   2
+#define  SAMD21_SYSTICK_CSR_CLKSOURCE_EXTERNAL         0
+#define  SAMD21_SYSTICK_CSR_CLKSOURCE_HCLK_8           1
+#define SAMD21_SYSTICK_CSR_COUNTFLAG   16
+
+#define SAMD21_SYSTICK_PRI             15
+
+/* The NVIC starts at 0xe000e100, so add that to the offsets to find the absolute address */
+
+struct samd21_nvic {
+       vuint32_t       iser;           /* 0x000 0xe000e100 Set Enable Register */
+
+       uint8_t         _unused020[0x080 - 0x004];
+
+       vuint32_t       icer;           /* 0x080 0xe000e180 Clear Enable Register */
+
+       uint8_t         _unused0a0[0x100 - 0x084];
+
+       vuint32_t       ispr;           /* 0x100 0xe000e200 Set Pending Register */
+
+       uint8_t         _unused120[0x180 - 0x104];
+
+       vuint32_t       icpr;           /* 0x180 0xe000e280 Clear Pending Register */
+
+       uint8_t         _unused1a0[0x300 - 0x184];
+
+       vuint32_t       ipr[8];         /* 0x300 0xe000e400 Priority Register */
+};
+
+extern struct samd21_nvic samd21_nvic;
+
+#define samd21_nvic (*(struct samd21_nvic *) 0xe000e100)
+
+#define SAMD21_NVIC_ISR_PM_POS         0
+#define SAMD21_NVIC_ISR_SYSCTRL_POS    1
+#define SAMD21_NVIC_ISR_WDT_POS                2
+#define SAMD21_NVIC_ISR_RTC_POS                3
+#define SAMD21_NVIC_ISR_EIC_POS                4
+#define SAMD21_NVIC_ISR_NVMCTRL_POS    5
+#define SAMD21_NVIC_ISR_DMAC_POS       6
+#define SAMD21_NVIC_ISR_USB_POS                7
+#define SAMD21_NVIC_ISR_EVSYS_POS      8
+#define SAMD21_NVIC_ISR_SERCOM0_POS    9
+#define SAMD21_NVIC_ISR_SERCOM1_POS    10
+#define SAMD21_NVIC_ISR_SERCOM2_POS    11
+#define SAMD21_NVIC_ISR_SERCOM3_POS    12
+#define SAMD21_NVIC_ISR_SERCOM4_POS    13
+#define SAMD21_NVIC_ISR_SERCOM5_POS    14
+#define SAMD21_NVIC_ISR_TCC0_POS       15
+#define SAMD21_NVIC_ISR_TCC1_POS       16
+#define SAMD21_NVIC_ISR_TCC2_POS       17
+#define SAMD21_NVIC_ISR_TC3_POS                18
+#define SAMD21_NVIC_ISR_TC4_POS                19
+#define SAMD21_NVIC_ISR_TC5_POS                20
+#define SAMD21_NVIC_ISR_TC6_POS                21
+#define SAMD21_NVIC_ISR_TC7_POS                22
+#define SAMD21_NVIC_ISR_ADC_POS                23
+#define SAMD21_NVIC_ISR_AC_POS         24
+#define SAMD21_NVIC_ISR_DAC_POS                25
+#define SAMD21_NVIC_ISR_PTC_POS                26
+#define SAMD21_NVIC_ISR_I2S_POS                27
+#define SAMD21_NVIC_ISR_AC1_POS                28
+#define SAMD21_NVIC_ISR_TCC3_POS       29
+
+#define IRQ_MASK(irq)  (1 << (irq))
+#define IRQ_BOOL(v,irq)        (((v) >> (irq)) & 1)
+
+static inline void
+samd21_nvic_set_enable(int irq) {
+       samd21_nvic.iser = IRQ_MASK(irq);
+}
+
+static inline void
+samd21_nvic_clear_enable(int irq) {
+       samd21_nvic.icer = IRQ_MASK(irq);
+}
+
+static inline int
+samd21_nvic_enabled(int irq) {
+       return IRQ_BOOL(samd21_nvic.iser, irq);
+}
+
+static inline void
+samd21_nvic_set_pending(int irq) {
+       samd21_nvic.ispr = IRQ_MASK(irq);
+}
+
+static inline void
+samd21_nvic_clear_pending(int irq) {
+       samd21_nvic.icpr = IRQ_MASK(irq);
+}
+
+static inline int
+samd21_nvic_pending(int irq) {
+       return IRQ_BOOL(samd21_nvic.ispr, irq);
+}
+
+#define IRQ_PRIO_REG(irq)      ((irq) >> 2)
+#define IRQ_PRIO_BIT(irq)      (((irq) & 3) << 3)
+#define IRQ_PRIO_MASK(irq)     (0xffU << IRQ_PRIO_BIT(irq))
+
+static inline void
+samd21_nvic_set_priority(int irq, uint8_t prio) {
+       int             n = IRQ_PRIO_REG(irq);
+       uint32_t        v;
+
+       v = samd21_nvic.ipr[n];
+       v &= ~IRQ_PRIO_MASK(irq);
+       v |= (prio) << IRQ_PRIO_BIT(irq);
+       samd21_nvic.ipr[n] = v;
+}
+
+static inline uint8_t
+samd21_nvic_get_priority(int irq) {
+       return (samd21_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0);
+}
+
+
+
+/* Cortex M0+ SCB */
+
+struct samd21_scb {
+       vuint32_t       cpuid;
+       vuint32_t       icsr;
+       vuint32_t       vtor;
+       vuint32_t       aircr;
+
+       vuint32_t       scr;
+       vuint32_t       ccr;
+       vuint32_t       shpr1;
+       vuint32_t       shpr2;
+
+       vuint32_t       shpr3;
+       vuint32_t       shcrs;
+       vuint32_t       cfsr;
+       vuint32_t       hfsr;
+
+       uint32_t        unused_30;
+       vuint32_t       mmfar;
+       vuint32_t       bfar;
+};
+
+extern struct samd21_scb samd21_scb;
+
+#define samd21_scb (*(struct samd21_scb *) 0xe000ed00)
+
+#define SAMD21_SCB_AIRCR_VECTKEY       16
+#define  SAMD21_SCB_AIRCR_VECTKEY_KEY          0x05fa
+#define SAMD21_SCB_AIRCR_PRIGROUP      8
+#define SAMD21_SCB_AIRCR_SYSRESETREQ   2
+#define SAMD21_SCB_AIRCR_VECTCLRACTIVE 1
+#define SAMD21_SCB_AIRCR_VECTRESET     0
+
+/* The NVM Calibration and auxiliary space starts at 0x00800000 */
+
+struct samd21_aux0 {
+       vuint64_t       userrow;
+};
+
+extern struct samd21_aux0 samd21_aux0;
+
+#define samd21_aux0 (*(struct samd21_aux0 *) 0x00804000)
+
+#define SAMD21_AUX0_USERROW_BOOTPROT   0
+#define SAMD21_AUX0_USERROW_EEPROM             4
+#define SAMD21_AUX0_USERROW_BOD33_LEVEL        8
+#define SAMD21_AUX0_USERROW_BOD33_ENABLE       14
+#define SAMD21_AUX0_USERROW_BOD33_ACTION       15
+#define SAMD21_AUX0_USERROW_WDT_ENABLE 25
+#define SAMD21_AUX0_USERROW_WDT_ALWAYS_ON      26
+#define SAMD21_AUX0_USERROW_WDT_PERIOD 27
+#define SAMD21_AUX0_USERROW_WDT_WINDOW 31
+#define SAMD21_AUX0_USERROW_WDT_EWOFFSET       35
+#define SAMD21_AUX0_USERROW_WDT_WEN            39
+#define SAMD21_AUX0_USERROW_BOD33_HYST 40
+#define SAMD21_AUX0_USERROW_LOCK               48
+
+struct samd21_aux1 {
+       vuint64_t       reserved_00;
+       vuint64_t       device_config;
+
+       vuint64_t       reserved_10;
+       vuint64_t       reserved_18;
+
+       vuint64_t       calibration;
+       vuint64_t       reserved_28;
+};
+
+extern struct samd21_aux1 samd21_aux1;
+
+#define samd21_aux1 (*(struct samd21_aux1 *) 0x00806000)
+
+#define SAMD21_AUX1_CALIBRATION_ADC_LINEARITY  27
+#define  SAMD21_AUX1_CALIBRATION_ADC_LINEARITY_MASK    0xff
+#define SAMD21_AUX1_CALIBRATION_ADC_BIASCAL    35
+#define  SAMD21_AUX1_CALIBRATION_ADC_BIASCAL_MASK      0x7
+#define SAMD21_AUX1_CALIBRATION_OSC32K_CAL     38
+#define SAMD21_AUX1_CALIBRATION_USB_TRANSN     45
+#define  SAMD21_AUX1_CALIBRATION_USB_TRANSN_MASK       0x1f
+#define SAMD21_AUX1_CALIBRATION_USB_TRANSP     50
+#define  SAMD21_AUX1_CALIBRATION_USB_TRANSP_MASK       0x1f
+#define SAMD21_AUX1_CALIBRATION_USB_TRIM       55
+#define  SAMD21_AUX1_CALIBRATION_USB_TRIM_MASK         0x07
+#define SAMD21_AUX1_CALIBRATION_DFLL48M_COARSE_CAL     58
+#define  SAMD21_AUX1_CALIBRATION_DFLL48M_COARSE_CAL_MASK       0x3f
+
+struct samd21_serial {
+       vuint32_t       reserved_00;
+       vuint32_t       reserved_04;
+       vuint32_t       reserved_08;
+       vuint32_t       word0;
+
+       vuint32_t       reserved_10;
+       vuint32_t       reserved_14;
+       vuint32_t       reserved_18;
+       vuint32_t       reserved_1c;
+
+       vuint32_t       reserved_20;
+       vuint32_t       reserved_24;
+       vuint32_t       reserved_28;
+       vuint32_t       reserved_2c;
+
+       vuint32_t       reserved_30;
+       vuint32_t       reserved_34;
+       vuint32_t       reserved_38;
+       vuint32_t       reserved_3c;
+
+       vuint32_t       word1;
+       vuint32_t       word2;
+       vuint32_t       word3;
+       vuint32_t       reserved_4c;
+};
+
+extern struct samd21_serial samd21_serial;
+
+#define samd21_serial (*(struct samd21_serial *) 0x0080a000)
+
+static inline void
+samd21_gclk_wait_sync(void)
+{
+       while (samd21_gclk.status & (1 << SAMD21_GCLK_STATUS_SYNCBUSY))
+               ;
+}
+
+static inline void
+samd21_dfll_wait_sync(void)
+{
+       while ((samd21_sysctrl.pclksr & (1 << SAMD21_SYSCTRL_PCLKSR_DFLLRDY)) == 0)
+               ;
+}
+
+static inline void
+samd21_gclk_gendiv(uint32_t id, uint32_t div)
+{
+       if (div == 1)
+               div = 0;
+       samd21_gclk.gendiv = ((id << SAMD21_GCLK_GENDIV_ID) |
+                             (div << SAMD21_GCLK_GENDIV_DIV));
+       samd21_gclk_wait_sync();
+}
+
+static inline void
+samd21_gclk_genctrl(uint32_t src, uint32_t id)
+{
+       samd21_gclk.genctrl = ((id << SAMD21_GCLK_GENCTRL_ID) |
+                              (src << SAMD21_GCLK_GENCTRL_SRC) |
+                              (0 << SAMD21_GCLK_GENCTRL_OE) |
+                              (1 << SAMD21_GCLK_GENCTRL_GENEN));
+       samd21_gclk_wait_sync();
+}
+
+static inline void
+samd21_gclk_clkctrl(uint32_t gen, uint32_t id)
+{
+       samd21_gclk.clkctrl = (uint16_t) ((gen << SAMD21_GCLK_CLKCTRL_GEN) |
+                                         (id << SAMD21_GCLK_CLKCTRL_ID) |
+                                         (1U << SAMD21_GCLK_CLKCTRL_CLKEN));
+       samd21_gclk_wait_sync();
+}
+
+#define isr_decl(name) \
+       void samd21_ ## name ## _isr(void)
+
+isr_decl(halt);
+isr_decl(ignore);
+isr_decl(nmi);
+isr_decl(hardfault);
+isr_decl(memmanage);
+isr_decl(busfault);
+isr_decl(usagefault);
+isr_decl(svc);
+isr_decl(debugmon);
+isr_decl(pendsv);
+isr_decl(systick);
+isr_decl(pm);          /* IRQ0 */
+isr_decl(sysctrl);
+isr_decl(wdt);
+isr_decl(rtc);
+isr_decl(eic);
+isr_decl(nvmctrl);
+isr_decl(dmac);
+isr_decl(usb);
+isr_decl(evsys);
+isr_decl(sercom0);
+isr_decl(sercom1);
+isr_decl(sercom2);
+isr_decl(sercom3);
+isr_decl(sercom4);
+isr_decl(sercom5);
+isr_decl(tcc0);
+isr_decl(tcc1);
+isr_decl(tcc2);
+isr_decl(tc3);
+isr_decl(tc4);
+isr_decl(tc5);
+isr_decl(tc6);
+isr_decl(tc7);
+isr_decl(adc);
+isr_decl(ac);
+isr_decl(dac);
+isr_decl(ptc);
+isr_decl(i2s);
+isr_decl(ac1);
+isr_decl(tcc3);
+
+#undef isr_decl
+
+#endif /* _SAMD21_H_ */