1 /*
2  * Copyright (c) 2024 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "hpm_esc_drv.h"
9 
10 #ifndef HPM_ESC_DRV_DEFAULT_RETRY_COUNT
11 #define HPM_ESC_DRV_DEFAULT_RETRY_COUNT (0xA0000000U)
12 #endif
13 
esc_mdio_read(ESC_Type * ptr,uint8_t phy_addr,uint8_t reg_addr,uint16_t * data)14 hpm_stat_t esc_mdio_read(ESC_Type *ptr, uint8_t phy_addr, uint8_t reg_addr, uint16_t *data)
15 {
16     uint32_t retry;
17 
18     ptr->MIIM_PDI_ACC_STAT = 1; /* PDI access MII management interface */
19 
20     /* wait for MII idle */
21     retry = 0;
22     while ((ptr->MII_MNG_CS & ESC_MII_MNG_CS_BUSY_MASK) != 0) {
23         if (retry > HPM_ESC_DRV_DEFAULT_RETRY_COUNT) {
24             break;
25         }
26         retry++;
27     }
28     if (retry > HPM_ESC_DRV_DEFAULT_RETRY_COUNT) {
29         return status_timeout;
30     }
31 
32     /* set PHY address and register address */
33     ptr->PHY_ADDR = phy_addr;
34     ptr->PHY_REG_ADDR = reg_addr;
35 
36     /* read command */
37     ptr->MII_MNG_CS = (ptr->MII_MNG_CS & ~ESC_MII_MNG_CS_CMD_MASK) | ESC_MII_MNG_CS_CMD_SET(1);
38 
39     /* wait command done */
40     retry = 0;
41     while ((ptr->MII_MNG_CS & ESC_MII_MNG_CS_BUSY_MASK) != 0) {
42         if (retry > HPM_ESC_DRV_DEFAULT_RETRY_COUNT) {
43             break;
44         }
45         retry++;
46     }
47     if (retry > HPM_ESC_DRV_DEFAULT_RETRY_COUNT) {
48         return status_timeout;
49     }
50 
51     /* check error status */
52     if ((ptr->MII_MNG_CS & ESC_MII_MNG_CS_CMD_ERR_MASK) != 0) {
53         return status_fail;
54     }
55 
56     /* check error status */
57     if ((ptr->MII_MNG_CS & ESC_MII_MNG_CS_CMD_ERR_MASK) != 0) {
58         return status_fail;
59     }
60 
61     *data = ptr->PHY_DATA;
62 
63     return status_success;
64 }
65 
esc_mdio_write(ESC_Type * ptr,uint8_t phy_addr,uint8_t reg_addr,uint16_t data)66 hpm_stat_t esc_mdio_write(ESC_Type *ptr, uint8_t phy_addr, uint8_t reg_addr, uint16_t data)
67 {
68     uint32_t retry;
69 
70     ptr->MIIM_PDI_ACC_STAT = 1; /* PDI access MII management interface */
71 
72     /* wait for MII idle */
73     retry = 0;
74     while ((ptr->MII_MNG_CS & ESC_MII_MNG_CS_BUSY_MASK) != 0) {
75         if (retry > HPM_ESC_DRV_DEFAULT_RETRY_COUNT) {
76             break;
77         }
78         retry++;
79     }
80     if (retry > HPM_ESC_DRV_DEFAULT_RETRY_COUNT) {
81         return status_timeout;
82     }
83 
84 
85     /* set PHY address, register address and register value */
86     ptr->PHY_ADDR = phy_addr;
87     ptr->PHY_REG_ADDR = reg_addr;
88     ptr->PHY_DATA = data;
89 
90     /* write command */
91     ptr->MII_MNG_CS = (ptr->MII_MNG_CS & ~ESC_MII_MNG_CS_CMD_MASK) | ESC_MII_MNG_CS_WEN_MASK | ESC_MII_MNG_CS_CMD_SET(2);
92 
93     /* wait command done */
94     retry = 0;
95     while ((ptr->MII_MNG_CS & ESC_MII_MNG_CS_BUSY_MASK) != 0) {
96         if (retry > HPM_ESC_DRV_DEFAULT_RETRY_COUNT) {
97             break;
98         }
99         retry++;
100     }
101     if (retry > HPM_ESC_DRV_DEFAULT_RETRY_COUNT) {
102         return status_timeout;
103     }
104 
105     /* check error status */
106     if ((ptr->MII_MNG_CS & ESC_MII_MNG_CS_CMD_ERR_MASK) != 0) {
107         return status_fail;
108     }
109 
110     /* check error status */
111     if ((ptr->MII_MNG_CS & ESC_MII_MNG_CS_CMD_ERR_MASK) != 0) {
112         return status_fail;
113     }
114 
115     return status_success;
116 }
117 
118 /* Loding ESC EEPROM, EtherCAT communication is possible even if the EEPROM is blank */
esc_check_eeprom_loading(ESC_Type * ptr)119 hpm_stat_t esc_check_eeprom_loading(ESC_Type *ptr)
120 {
121     hpm_stat_t stat = status_success;
122     uint32_t retry = 0;
123 
124     while (1) {
125         /* 0x110 bit0 eeprom load correctly */
126         if ((ptr->ESC_DL_STAT & ESC_ESC_DL_STAT_EPLC_MASK) == ESC_ESC_DL_STAT_EPLC_MASK) {
127             stat = status_success; /* Loading successful, PDI operations */
128             break;
129         }
130 
131         /* 0x502 bit13 ack or cmd error */
132         if ((ptr->EEPROM_CTRL_STAT & ESC_EEPROM_CTRL_STAT_ERR_ACK_CMD_MASK) == ESC_EEPROM_CTRL_STAT_ERR_ACK_CMD_MASK) { /* ACMDERR = 1 */
133             stat = status_esc_eeprom_ack_error; /* I2C bus error */
134             break;
135         } else {
136             if ((ptr->EEPROM_CTRL_STAT & ESC_EEPROM_CTRL_STAT_CKSM_ERR_MASK) == ESC_EEPROM_CTRL_STAT_CKSM_ERR_MASK) {   /* ACMDERR,CKSUMERR = 01 */
137                 stat = status_esc_eeprom_checksum_error; /* EEPROM is loaded, but it is blank and cause checksum error  */
138                 break;
139             }
140         }
141 
142         if (retry > HPM_ESC_DRV_DEFAULT_RETRY_COUNT) {
143             stat = status_timeout;
144             break;
145         }
146         retry++;
147     }
148 
149     return stat;
150 }
151