summaryrefslogtreecommitdiff
path: root/bsp/nuvoton/libraries/m480/rtt_port/drv_hsotg.c
blob: 5859f3244f24de41a39a3b3baef783b2ff52222e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/**************************************************************************//**
*
* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date            Author       Notes
* 2020-05-22      klcheng      First version
*
******************************************************************************/
#include <rtconfig.h>

#if defined(BSP_USING_HSOTG)
#include <rtdevice.h>
#include <rtdbg.h>
#include "NuMicro.h"


/* This delay must be at least 10 us */
static void _usb_init_delay(void)
{
    volatile uint32_t i = 0x1000;

    while (i--)
        __NOP();

    return;
}

/* Check current usb role */
static void usb_role(void)
{
    uint32_t status;

    status = (HSOTG->STATUS) & (HSOTG_STATUS_ASHOST_Msk | HSOTG_STATUS_ASPERI_Msk | HSOTG_STATUS_IDSTS_Msk);

    if (status == (HSOTG_STATUS_IDSTS_Msk | HSOTG_STATUS_ASPERI_Msk))
        rt_kprintf("usb frame acts as peripheral\n");

    else if (status == HSOTG_STATUS_ASHOST_Msk)
        rt_kprintf("usb frame acts as host\n");

    else
        rt_kprintf("usb frame is unknown state: 0x%x\n", status);

    return;
}
MSH_CMD_EXPORT_ALIAS(usb_role, usb_role, check usb role);


static int hsotg_init(void)
{
    SYS_UnlockReg();

    /* Set HSOTG as ID dependent role */
    SYS->USBPHY = SYS_USBPHY_HSUSBEN_Msk | (0x2 << SYS_USBPHY_HSUSBROLE_Pos);

    /* user should keep HSUSB PHY at reset mode at lease 10 us before changing to active mode */
    _usb_init_delay();
    SYS->USBPHY |= SYS_USBPHY_HSUSBACT_Msk;

    /* Enable OTG and ID detection function */
    HSOTG_ENABLE_PHY();
    HSOTG_ENABLE_ID_DETECT();
    NVIC_EnableIRQ(USBOTG20_IRQn);

    /* clear interrupt and enable relative interrupts */
    HSOTG_ENABLE_INT(HSOTG_INTEN_IDCHGIEN_Msk | HSOTG_INTEN_HOSTIEN_Msk | HSOTG_INTEN_PDEVIEN_Msk |
                     HSOTG_INTEN_BVLDCHGIEN_Msk | HSOTG_INTEN_AVLDCHGIEN_Msk);

    SYS_LockReg();

    return (int)RT_EOK;
}
INIT_DEVICE_EXPORT(hsotg_init);


/* HSOTG interrupt entry */
void USBOTG20_IRQHandler(void)
{
    __IO uint32_t reg;

    reg = HSOTG->INTSTS;

    /* usb id pin status change */
    if (reg & HSOTG_INTSTS_IDCHGIF_Msk)
    {
        HSOTG_CLR_INT_FLAG(HSOTG_INTSTS_IDCHGIF_Msk);
        LOG_D("usb id change");
    }

    /* usb acts as host */
    if (reg & HSOTG_INTSTS_HOSTIF_Msk)
    {
        HSOTG_CLR_INT_FLAG(HSOTG_INTSTS_HOSTIF_Msk);
        LOG_D("usb acts as host");
    }

    /* usb acts as peripheral */
    if (reg & HSOTG_INTSTS_PDEVIF_Msk)
    {
        HSOTG_CLR_INT_FLAG(HSOTG_INTSTS_PDEVIF_Msk);
        LOG_D("usb acts as peripheral");
    }

    /* A-device session valid state change */
    if (reg & HSOTG_INTSTS_AVLDCHGIF_Msk)
    {
        HSOTG_CLR_INT_FLAG(HSOTG_INTSTS_AVLDCHGIF_Msk);
        LOG_D("usb a-device session valid state change");
    }

    /* B-device session valid state change */
    if (reg & HSOTG_INTSTS_BVLDCHGIF_Msk)
    {
        HSOTG_CLR_INT_FLAG(HSOTG_INTSTS_BVLDCHGIF_Msk);
        LOG_D("usb b-device session valid state change");
    }
}

#endif /* defined(BSP_USING_HSOTG) */