github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/board/nxp/mx6ullevk/enet.go (about) 1 // MCIMX6ULL-EVK support for tamago/arm 2 // https://github.com/usbarmory/tamago 3 // 4 // Copyright (c) WithSecure Corporation 5 // https://foundry.withsecure.com 6 // 7 // Use of this source code is governed by the license 8 // that can be found in the LICENSE file. 9 10 package mx6ullevk 11 12 import ( 13 "errors" 14 15 "github.com/usbarmory/tamago/soc/nxp/enet" 16 "github.com/usbarmory/tamago/soc/nxp/imx6ul" 17 "github.com/usbarmory/tamago/soc/nxp/iomuxc" 18 ) 19 20 // Ethernet PHY configuration constants. 21 // 22 // On the MCIMX6ULL-EVK the ENET MACs are each connected to an KSZ8081RNB PHY, 23 // this board package configures them at 100 Mbps / Full-duplex mode. 24 const ( 25 KSZ_CTRL = 0x00 26 CTRL_RESET = 15 27 CTRL_SPEED = 13 28 CTRL_DUPLEX = 8 29 30 KSZ_INT = 0x1b 31 32 KSZ_PHYCTRL2 = 0x1f 33 CTRL2_HP_MDIX = 15 34 CTRL2_RMII = 7 35 CTRL2_LED = 4 36 ) 37 38 const ( 39 // ENET1 MUX 40 IOMUXC_SW_MUX_CTL_PAD_ENET1_RX_DATA0 = 0x020e00c4 41 IOMUXC_SW_MUX_CTL_PAD_ENET1_RX_DATA1 = 0x020e00c8 42 IOMUXC_SW_MUX_CTL_PAD_ENET1_RX_EN = 0x020e00cc 43 IOMUXC_SW_MUX_CTL_PAD_ENET1_TX_DATA0 = 0x020e00d0 44 IOMUXC_SW_MUX_CTL_PAD_ENET1_TX_DATA1 = 0x020e00d4 45 IOMUXC_SW_MUX_CTL_PAD_ENET1_TX_EN = 0x020e00d8 46 IOMUXC_SW_MUX_CTL_PAD_ENET1_TX_CLK = 0x020e00dc 47 IOMUXC_SW_MUX_CTL_PAD_ENET1_RX_ER = 0x020e00e0 48 49 // ENET1 PAD 50 IOMUXC_SW_PAD_CTL_PAD_ENET1_RX_DATA0 = 0x020e0350 51 IOMUXC_SW_PAD_CTL_PAD_ENET1_RX_DATA1 = 0x020e0354 52 IOMUXC_SW_PAD_CTL_PAD_ENET1_RX_EN = 0x020e0358 53 IOMUXC_SW_PAD_CTL_PAD_ENET1_TX_DATA0 = 0x020e035c 54 IOMUXC_SW_PAD_CTL_PAD_ENET1_TX_DATA1 = 0x020e0360 55 IOMUXC_SW_PAD_CTL_PAD_ENET1_TX_EN = 0x020e0364 56 IOMUXC_SW_PAD_CTL_PAD_ENET1_TX_CLK = 0x020e0368 57 IOMUXC_SW_PAD_CTL_PAD_ENET1_RX_ER = 0x020e036c 58 59 // ENET1 SELECT INPUT 60 IOMUXC_ENET1_REF_CLK1_SELECT_INPUT = 0x020e0574 61 IOMUXC_ENET1_MAC0_MDIO_SELECT_INPUT = 0x020e0578 62 63 // ENET2 MUX 64 IOMUXC_SW_MUX_CTL_PAD_ENET2_RX_DATA0 = 0x020e00e4 65 IOMUXC_SW_MUX_CTL_PAD_ENET2_RX_DATA1 = 0x020e00e8 66 IOMUXC_SW_MUX_CTL_PAD_ENET2_RX_EN = 0x020e00ec 67 IOMUXC_SW_MUX_CTL_PAD_ENET2_TX_DATA0 = 0x020e00f0 68 IOMUXC_SW_MUX_CTL_PAD_ENET2_TX_DATA1 = 0x020e00f4 69 IOMUXC_SW_MUX_CTL_PAD_ENET2_TX_EN = 0x020e00f8 70 IOMUXC_SW_MUX_CTL_PAD_ENET2_TX_CLK = 0x020e00fc 71 IOMUXC_SW_MUX_CTL_PAD_ENET2_RX_ER = 0x020e0100 72 73 // ENET2 PAD 74 IOMUXC_SW_PAD_CTL_PAD_ENET2_RX_DATA0 = 0x020e0370 75 IOMUXC_SW_PAD_CTL_PAD_ENET2_RX_DATA1 = 0x020e0374 76 IOMUXC_SW_PAD_CTL_PAD_ENET2_RX_EN = 0x020e0378 77 IOMUXC_SW_PAD_CTL_PAD_ENET2_TX_DATA0 = 0x020e037c 78 IOMUXC_SW_PAD_CTL_PAD_ENET2_TX_DATA1 = 0x020e0380 79 IOMUXC_SW_PAD_CTL_PAD_ENET2_TX_EN = 0x020e0384 80 IOMUXC_SW_PAD_CTL_PAD_ENET2_TX_CLK = 0x020e0388 81 IOMUXC_SW_PAD_CTL_PAD_ENET2_RX_ER = 0x020e038c 82 83 // ENET2 SELECT INPUT 84 IOMUXC_ENET2_REF_CLK2_SELECT_INPUT = 0x020e057c 85 IOMUXC_ENET2_MAC0_MDIO_SELECT_INPUT = 0x020e0580 86 87 // MDIO 88 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO06 = 0x020e0074 89 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO06 = 0x020e0300 90 91 // MDC 92 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO07 = 0x020e0304 93 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO07 = 0x020e0078 94 95 IOMUX_ALT0 = 0 96 IOMUX_ALT1 = 1 97 IOMUX_ALT4 = 4 98 99 DAISY_ENET1_TX_CLK_ALT4 = 0b10 100 DAISY_ENET2_TX_CLK_ALT4 = 0b10 101 DAISY_ENET1_GPIO1_IO06_ALT0 = 0 102 DAISY_ENET2_GPIO1_IO06_ALT1 = 1 103 ) 104 105 func init() { 106 imx6ul.ENET1.EnablePHY = EnablePHY 107 imx6ul.ENET2.EnablePHY = EnablePHY 108 109 imx6ul.ENET1.RMII = true 110 imx6ul.ENET2.RMII = true 111 } 112 113 func configurePHYPad(mux uint32, pad uint32, daisy uint32, mode uint32, ctl uint32) (p *iomuxc.Pad) { 114 p = &iomuxc.Pad{ 115 Mux: mux, 116 Pad: pad, 117 Daisy: daisy, 118 } 119 120 p.Mode(mode) 121 p.Ctl(ctl) 122 123 return 124 } 125 126 func ctl50() uint32 { 127 return (iomuxc.SW_PAD_CTL_DSE_2_R0_6 << iomuxc.SW_PAD_CTL_DSE) | 128 (iomuxc.SW_PAD_CTL_SPEED_50MHZ << iomuxc.SW_PAD_CTL_SPEED) | 129 (1 << iomuxc.SW_PAD_CTL_PUE) | (1 << iomuxc.SW_PAD_CTL_PKE) | 130 (iomuxc.SW_PAD_CTL_PUS_PULL_UP_100K << iomuxc.SW_PAD_CTL_PUS) | 131 (1 << iomuxc.SW_PAD_CTL_HYS) 132 } 133 134 func ctl100() uint32 { 135 return (iomuxc.SW_PAD_CTL_DSE_2_R0_6 << iomuxc.SW_PAD_CTL_DSE) | 136 (iomuxc.SW_PAD_CTL_SPEED_100MHZ << iomuxc.SW_PAD_CTL_SPEED) | 137 (1 << iomuxc.SW_PAD_CTL_PUE) | (1 << iomuxc.SW_PAD_CTL_PKE) | 138 (iomuxc.SW_PAD_CTL_PUS_PULL_UP_100K << iomuxc.SW_PAD_CTL_PUS) | 139 (1 << iomuxc.SW_PAD_CTL_HYS) 140 } 141 142 func configurePHY1Pads() { 143 // 50 Mhz pad 144 ctl50 := ctl50() 145 // 100 Mhz pad 146 ctl100 := ctl100() 147 148 // [ALT0] ENET1_RDATA01 149 configurePHYPad( 150 IOMUXC_SW_MUX_CTL_PAD_ENET1_RX_DATA0, 151 IOMUXC_SW_PAD_CTL_PAD_ENET1_RX_DATA0, 152 0, IOMUX_ALT0, ctl100) 153 154 // [ALT0] ENET1_RDATA01 155 configurePHYPad( 156 IOMUXC_SW_MUX_CTL_PAD_ENET1_RX_DATA1, 157 IOMUXC_SW_PAD_CTL_PAD_ENET1_RX_DATA1, 158 0, IOMUX_ALT0, ctl100) 159 160 // [ALT0] ENET1_RX_EN 161 configurePHYPad( 162 IOMUXC_SW_MUX_CTL_PAD_ENET1_RX_EN, 163 IOMUXC_SW_PAD_CTL_PAD_ENET1_RX_EN, 164 0, IOMUX_ALT0, ctl100) 165 166 // [ALT0] ENET1_TDATA00 167 configurePHYPad( 168 IOMUXC_SW_MUX_CTL_PAD_ENET1_TX_DATA0, 169 IOMUXC_SW_PAD_CTL_PAD_ENET1_TX_DATA0, 170 0, IOMUX_ALT0, ctl100) 171 172 // [ALT0] ENET1_TDATA01 173 configurePHYPad( 174 IOMUXC_SW_MUX_CTL_PAD_ENET1_TX_DATA1, 175 IOMUXC_SW_PAD_CTL_PAD_ENET1_TX_DATA1, 176 0, IOMUX_ALT0, ctl100) 177 178 // [ALT0] ENET1_TX_EN 179 configurePHYPad( 180 IOMUXC_SW_MUX_CTL_PAD_ENET1_TX_EN, 181 IOMUXC_SW_PAD_CTL_PAD_ENET1_TX_EN, 182 0, IOMUX_ALT0, ctl100) 183 184 // [ALT4] ENET1_REF_CLK / SION ENABLED 185 pad := configurePHYPad( 186 IOMUXC_SW_MUX_CTL_PAD_ENET1_TX_CLK, 187 IOMUXC_SW_PAD_CTL_PAD_ENET1_TX_CLK, 188 IOMUXC_ENET1_REF_CLK1_SELECT_INPUT, 189 IOMUX_ALT4, ctl50) 190 pad.Select(DAISY_ENET1_TX_CLK_ALT4) 191 pad.SoftwareInput(true) 192 193 // [ALT0] ENET1_RX_ER 194 configurePHYPad( 195 IOMUXC_SW_MUX_CTL_PAD_ENET1_RX_ER, 196 IOMUXC_SW_PAD_CTL_PAD_ENET1_RX_ER, 197 0, IOMUX_ALT0, ctl100) 198 199 // [ALT0] ENET1_MDIO 200 pad = configurePHYPad( 201 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO06, 202 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO06, 203 IOMUXC_ENET1_MAC0_MDIO_SELECT_INPUT, 204 IOMUX_ALT0, ctl100) 205 pad.Select(DAISY_ENET1_GPIO1_IO06_ALT0) 206 207 // [ALT0] ENET1_MDC 208 configurePHYPad( 209 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO07, 210 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO07, 211 0, IOMUX_ALT0, ctl100) 212 } 213 214 func configurePHY2Pads() { 215 // 50 Mhz pad 216 ctl50 := ctl50() 217 // 100 Mhz pad 218 ctl100 := ctl100() 219 220 // [ALT0] ENET2_RDATA01 221 configurePHYPad( 222 IOMUXC_SW_MUX_CTL_PAD_ENET2_RX_DATA0, 223 IOMUXC_SW_PAD_CTL_PAD_ENET2_RX_DATA0, 224 0, IOMUX_ALT0, ctl100) 225 226 // [ALT0] ENET2_RDATA01 227 configurePHYPad( 228 IOMUXC_SW_MUX_CTL_PAD_ENET2_RX_DATA1, 229 IOMUXC_SW_PAD_CTL_PAD_ENET2_RX_DATA1, 230 0, IOMUX_ALT0, ctl100) 231 232 // [ALT0] ENET2_RX_EN 233 configurePHYPad( 234 IOMUXC_SW_MUX_CTL_PAD_ENET2_RX_EN, 235 IOMUXC_SW_PAD_CTL_PAD_ENET2_RX_EN, 236 0, IOMUX_ALT0, ctl100) 237 238 // [ALT0] ENET2_TDATA00 239 configurePHYPad( 240 IOMUXC_SW_MUX_CTL_PAD_ENET2_TX_DATA0, 241 IOMUXC_SW_PAD_CTL_PAD_ENET2_TX_DATA0, 242 0, IOMUX_ALT0, ctl100) 243 244 // [ALT0] ENET2_TDATA01 245 configurePHYPad( 246 IOMUXC_SW_MUX_CTL_PAD_ENET2_TX_DATA1, 247 IOMUXC_SW_PAD_CTL_PAD_ENET2_TX_DATA1, 248 0, IOMUX_ALT0, ctl100) 249 250 // [ALT0] ENET2_TX_EN 251 configurePHYPad( 252 IOMUXC_SW_MUX_CTL_PAD_ENET2_TX_EN, 253 IOMUXC_SW_PAD_CTL_PAD_ENET2_TX_EN, 254 0, IOMUX_ALT0, ctl100) 255 256 // [ALT4] ENET2_REF_CLK / SION ENABLED 257 pad := configurePHYPad( 258 IOMUXC_SW_MUX_CTL_PAD_ENET2_TX_CLK, 259 IOMUXC_SW_PAD_CTL_PAD_ENET2_TX_CLK, 260 IOMUXC_ENET2_REF_CLK2_SELECT_INPUT, 261 IOMUX_ALT4, ctl50) 262 pad.Select(DAISY_ENET2_TX_CLK_ALT4) 263 pad.SoftwareInput(true) 264 265 // [ALT0] ENET2_RX_ER 266 configurePHYPad( 267 IOMUXC_SW_MUX_CTL_PAD_ENET2_RX_ER, 268 IOMUXC_SW_PAD_CTL_PAD_ENET2_RX_ER, 269 0, IOMUX_ALT0, ctl100) 270 271 // [ALT0] ENET2_MDIO 272 pad = configurePHYPad( 273 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO06, 274 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO06, 275 IOMUXC_ENET2_MAC0_MDIO_SELECT_INPUT, 276 IOMUX_ALT1, ctl100) 277 pad.Select(DAISY_ENET2_GPIO1_IO06_ALT1) 278 279 // [ALT0] ENET2_MDC 280 configurePHYPad( 281 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO07, 282 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO07, 283 0, IOMUX_ALT1, ctl100) 284 } 285 286 func EnablePHY(eth *enet.ENET) error { 287 var pa int 288 289 switch eth.Index { 290 case 1: 291 pa = 2 292 configurePHY1Pads() 293 case 2: 294 pa = 1 295 configurePHY2Pads() 296 default: 297 return errors.New("invalid index") 298 } 299 300 // Software reset 301 eth.WritePHYRegister(pa, KSZ_CTRL, (1 << CTRL_RESET)) 302 // HP Auto MDI/MDI-X mode, RMII 50MHz, LEDs: Activity/Link 303 eth.WritePHYRegister(pa, KSZ_PHYCTRL2, (1<<CTRL2_HP_MDIX)|(1<<CTRL2_RMII)|(1<<CTRL2_LED)) 304 // 100 Mbps, Full-duplex 305 eth.WritePHYRegister(pa, KSZ_CTRL, (1<<CTRL_SPEED)|(1<<CTRL_DUPLEX)) 306 // enable interrupts 307 eth.WritePHYRegister(pa, KSZ_INT, 0xff00) 308 309 return nil 310 }