1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2012 Freescale Semiconductor, Inc. 4 * Author: Fabio Estevam <fabio.estevam@freescale.com> 5 * 6 * Copyright (C) 2013, 2014 TQ Systems (ported SabreSD to TQMa6x) 7 * Author: Markus Niebel <markus.niebel@tq-group.com> 8 */ 9 10 #include <asm/io.h> 11 #include <asm/arch/clock.h> 12 #include <asm/arch/mx6-pins.h> 13 #include <asm/arch/imx-regs.h> 14 #include <asm/arch/iomux.h> 15 #include <asm/arch/sys_proto.h> 16 #include <linux/errno.h> 17 #include <asm/gpio.h> 18 #include <asm/mach-imx/mxc_i2c.h> 19 20 #include <common.h> 21 #include <fsl_esdhc.h> 22 #include <linux/libfdt.h> 23 #include <malloc.h> 24 #include <i2c.h> 25 #include <micrel.h> 26 #include <miiphy.h> 27 #include <mmc.h> 28 #include <netdev.h> 29 30 #include "tqma6_bb.h" 31 32 #define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 33 PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) 34 35 #define USDHC_CLK_PAD_CTRL (PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ 36 PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) 37 38 #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ 39 PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) 40 41 #define GPIO_OUT_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW | \ 42 PAD_CTL_DSE_40ohm | PAD_CTL_HYS) 43 44 #define GPIO_IN_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW | \ 45 PAD_CTL_DSE_40ohm | PAD_CTL_HYS) 46 47 #define SPI_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 48 PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) 49 50 #define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 51 PAD_CTL_DSE_80ohm | PAD_CTL_HYS | \ 52 PAD_CTL_ODE | PAD_CTL_SRE_FAST) 53 54 #if defined(CONFIG_TQMA6Q) 55 56 #define IOMUX_SW_PAD_CTRL_GRP_DDR_TYPE_RGMII 0x02e0790 57 #define IOMUX_SW_PAD_CTRL_GRP_RGMII_TERM 0x02e07ac 58 59 #elif defined(CONFIG_TQMA6S) || defined(CONFIG_TQMA6DL) 60 61 #define IOMUX_SW_PAD_CTRL_GRP_DDR_TYPE_RGMII 0x02e0768 62 #define IOMUX_SW_PAD_CTRL_GRP_RGMII_TERM 0x02e0788 63 64 #else 65 66 #error "need to select module" 67 68 #endif 69 70 #define ENET_RX_PAD_CTRL (PAD_CTL_DSE_34ohm) 71 #define ENET_TX_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_DSE_34ohm) 72 #define ENET_CLK_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_HIGH | \ 73 PAD_CTL_DSE_34ohm) 74 #define ENET_MDIO_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 75 PAD_CTL_DSE_60ohm) 76 77 /* disable on die termination for RGMII */ 78 #define IOMUX_SW_PAD_CTRL_GRP_RGMII_TERM_DISABLE 0x00000000 79 /* optimised drive strength for 1.0 .. 1.3 V signal on RGMII */ 80 #define IOMUX_SW_PAD_CTRL_GRP_DDR_TYPE_RGMII_1P2V 0x00080000 81 /* optimised drive strength for 1.3 .. 2.5 V signal on RGMII */ 82 #define IOMUX_SW_PAD_CTRL_GRP_DDR_TYPE_RGMII_1P5V 0x000C0000 83 84 #define ENET_PHY_RESET_GPIO IMX_GPIO_NR(1, 25) 85 86 static iomux_v3_cfg_t const mba6_enet_pads[] = { 87 NEW_PAD_CTRL(MX6_PAD_ENET_MDIO__ENET_MDIO, ENET_MDIO_PAD_CTRL), 88 NEW_PAD_CTRL(MX6_PAD_ENET_MDC__ENET_MDC, ENET_MDIO_PAD_CTRL), 89 90 NEW_PAD_CTRL(MX6_PAD_RGMII_TXC__RGMII_TXC, ENET_TX_PAD_CTRL), 91 NEW_PAD_CTRL(MX6_PAD_RGMII_TD0__RGMII_TD0, ENET_TX_PAD_CTRL), 92 NEW_PAD_CTRL(MX6_PAD_RGMII_TD1__RGMII_TD1, ENET_TX_PAD_CTRL), 93 NEW_PAD_CTRL(MX6_PAD_RGMII_TD2__RGMII_TD2, ENET_TX_PAD_CTRL), 94 NEW_PAD_CTRL(MX6_PAD_RGMII_TD3__RGMII_TD3, ENET_TX_PAD_CTRL), 95 NEW_PAD_CTRL(MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL, 96 ENET_TX_PAD_CTRL), 97 NEW_PAD_CTRL(MX6_PAD_ENET_REF_CLK__ENET_TX_CLK, ENET_CLK_PAD_CTRL), 98 /* 99 * these pins are also used for config strapping by phy 100 */ 101 NEW_PAD_CTRL(MX6_PAD_RGMII_RD0__RGMII_RD0, ENET_RX_PAD_CTRL), 102 NEW_PAD_CTRL(MX6_PAD_RGMII_RD1__RGMII_RD1, ENET_RX_PAD_CTRL), 103 NEW_PAD_CTRL(MX6_PAD_RGMII_RD2__RGMII_RD2, ENET_RX_PAD_CTRL), 104 NEW_PAD_CTRL(MX6_PAD_RGMII_RD3__RGMII_RD3, ENET_RX_PAD_CTRL), 105 NEW_PAD_CTRL(MX6_PAD_RGMII_RXC__RGMII_RXC, ENET_RX_PAD_CTRL), 106 NEW_PAD_CTRL(MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL, 107 ENET_RX_PAD_CTRL), 108 /* KSZ9031 PHY Reset */ 109 NEW_PAD_CTRL(MX6_PAD_ENET_CRS_DV__GPIO1_IO25, GPIO_OUT_PAD_CTRL), 110 }; 111 112 static void mba6_setup_iomuxc_enet(void) 113 { 114 struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; 115 116 /* clear gpr1[ENET_CLK_SEL] for externel clock */ 117 clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK); 118 119 __raw_writel(IOMUX_SW_PAD_CTRL_GRP_RGMII_TERM_DISABLE, 120 (void *)IOMUX_SW_PAD_CTRL_GRP_RGMII_TERM); 121 __raw_writel(IOMUX_SW_PAD_CTRL_GRP_DDR_TYPE_RGMII_1P5V, 122 (void *)IOMUX_SW_PAD_CTRL_GRP_DDR_TYPE_RGMII); 123 124 imx_iomux_v3_setup_multiple_pads(mba6_enet_pads, 125 ARRAY_SIZE(mba6_enet_pads)); 126 127 /* Reset PHY */ 128 gpio_direction_output(ENET_PHY_RESET_GPIO , 0); 129 /* Need delay 10ms after power on according to KSZ9031 spec */ 130 mdelay(10); 131 gpio_set_value(ENET_PHY_RESET_GPIO, 1); 132 /* 133 * KSZ9031 manual: 100 usec wait time after reset before communication 134 * over MDIO 135 * BUGBUG: hardware has an RC const that needs > 10 msec from 0->1 on 136 * reset before the phy sees a high level 137 */ 138 mdelay(15); 139 } 140 141 static iomux_v3_cfg_t const mba6_uart2_pads[] = { 142 NEW_PAD_CTRL(MX6_PAD_SD4_DAT4__UART2_RX_DATA, UART_PAD_CTRL), 143 NEW_PAD_CTRL(MX6_PAD_SD4_DAT7__UART2_TX_DATA, UART_PAD_CTRL), 144 }; 145 146 static void mba6_setup_iomuxc_uart(void) 147 { 148 imx_iomux_v3_setup_multiple_pads(mba6_uart2_pads, 149 ARRAY_SIZE(mba6_uart2_pads)); 150 } 151 152 #define USDHC2_CD_GPIO IMX_GPIO_NR(1, 4) 153 #define USDHC2_WP_GPIO IMX_GPIO_NR(1, 2) 154 155 int tqma6_bb_board_mmc_getcd(struct mmc *mmc) 156 { 157 struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; 158 int ret = 0; 159 160 if (cfg->esdhc_base == USDHC2_BASE_ADDR) 161 ret = !gpio_get_value(USDHC2_CD_GPIO); 162 163 return ret; 164 } 165 166 int tqma6_bb_board_mmc_getwp(struct mmc *mmc) 167 { 168 struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; 169 int ret = 0; 170 171 if (cfg->esdhc_base == USDHC2_BASE_ADDR) 172 ret = gpio_get_value(USDHC2_WP_GPIO); 173 174 return ret; 175 } 176 177 static struct fsl_esdhc_cfg mba6_usdhc_cfg = { 178 .esdhc_base = USDHC2_BASE_ADDR, 179 .max_bus_width = 4, 180 }; 181 182 static iomux_v3_cfg_t const mba6_usdhc2_pads[] = { 183 NEW_PAD_CTRL(MX6_PAD_SD2_CLK__SD2_CLK, USDHC_CLK_PAD_CTRL), 184 NEW_PAD_CTRL(MX6_PAD_SD2_CMD__SD2_CMD, USDHC_PAD_CTRL), 185 NEW_PAD_CTRL(MX6_PAD_SD2_DAT0__SD2_DATA0, USDHC_PAD_CTRL), 186 NEW_PAD_CTRL(MX6_PAD_SD2_DAT1__SD2_DATA1, USDHC_PAD_CTRL), 187 NEW_PAD_CTRL(MX6_PAD_SD2_DAT2__SD2_DATA2, USDHC_PAD_CTRL), 188 NEW_PAD_CTRL(MX6_PAD_SD2_DAT3__SD2_DATA3, USDHC_PAD_CTRL), 189 /* CD */ 190 NEW_PAD_CTRL(MX6_PAD_GPIO_4__GPIO1_IO04, GPIO_IN_PAD_CTRL), 191 /* WP */ 192 NEW_PAD_CTRL(MX6_PAD_GPIO_2__GPIO1_IO02, GPIO_IN_PAD_CTRL), 193 }; 194 195 int tqma6_bb_board_mmc_init(bd_t *bis) 196 { 197 imx_iomux_v3_setup_multiple_pads(mba6_usdhc2_pads, 198 ARRAY_SIZE(mba6_usdhc2_pads)); 199 gpio_direction_input(USDHC2_CD_GPIO); 200 gpio_direction_input(USDHC2_WP_GPIO); 201 202 mba6_usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); 203 if (fsl_esdhc_initialize(bis, &mba6_usdhc_cfg)) 204 puts("Warning: failed to initialize SD\n"); 205 206 return 0; 207 } 208 209 static struct i2c_pads_info mba6_i2c1_pads = { 210 /* I2C1: MBa6x */ 211 .scl = { 212 .i2c_mode = NEW_PAD_CTRL(MX6_PAD_CSI0_DAT9__I2C1_SCL, 213 I2C_PAD_CTRL), 214 .gpio_mode = NEW_PAD_CTRL(MX6_PAD_CSI0_DAT9__GPIO5_IO27, 215 I2C_PAD_CTRL), 216 .gp = IMX_GPIO_NR(5, 27) 217 }, 218 .sda = { 219 .i2c_mode = NEW_PAD_CTRL(MX6_PAD_CSI0_DAT8__I2C1_SDA, 220 I2C_PAD_CTRL), 221 .gpio_mode = NEW_PAD_CTRL(MX6_PAD_CSI0_DAT8__GPIO5_IO26, 222 I2C_PAD_CTRL), 223 .gp = IMX_GPIO_NR(5, 26) 224 } 225 }; 226 227 static void mba6_setup_i2c(void) 228 { 229 int ret; 230 /* 231 * use logical index for bus, e.g. I2C1 -> 0 232 * warn on error 233 */ 234 ret = setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &mba6_i2c1_pads); 235 if (ret) 236 printf("setup I2C1 failed: %d\n", ret); 237 } 238 239 int board_phy_config(struct phy_device *phydev) 240 { 241 /* 242 * optimized pad skew values depends on CPU variant on the TQMa6x module: 243 * CONFIG_TQMA6Q: i.MX6Q/D 244 * CONFIG_TQMA6S: i.MX6S 245 * CONFIG_TQMA6DL: i.MX6DL 246 */ 247 #if defined(CONFIG_TQMA6Q) 248 #define MBA6X_KSZ9031_CTRL_SKEW 0x0032 249 #define MBA6X_KSZ9031_CLK_SKEW 0x03ff 250 #define MBA6X_KSZ9031_RX_SKEW 0x3333 251 #define MBA6X_KSZ9031_TX_SKEW 0x2036 252 #elif defined(CONFIG_TQMA6S) || defined(CONFIG_TQMA6DL) 253 #define MBA6X_KSZ9031_CTRL_SKEW 0x0030 254 #define MBA6X_KSZ9031_CLK_SKEW 0x03ff 255 #define MBA6X_KSZ9031_RX_SKEW 0x3333 256 #define MBA6X_KSZ9031_TX_SKEW 0x2052 257 #else 258 #error 259 #endif 260 /* min rx/tx ctrl delay */ 261 ksz9031_phy_extended_write(phydev, 2, 262 MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW, 263 MII_KSZ9031_MOD_DATA_NO_POST_INC, 264 MBA6X_KSZ9031_CTRL_SKEW); 265 /* min rx delay */ 266 ksz9031_phy_extended_write(phydev, 2, 267 MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW, 268 MII_KSZ9031_MOD_DATA_NO_POST_INC, 269 MBA6X_KSZ9031_RX_SKEW); 270 /* max tx delay */ 271 ksz9031_phy_extended_write(phydev, 2, 272 MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW, 273 MII_KSZ9031_MOD_DATA_NO_POST_INC, 274 MBA6X_KSZ9031_TX_SKEW); 275 /* rx/tx clk skew */ 276 ksz9031_phy_extended_write(phydev, 2, 277 MII_KSZ9031_EXT_RGMII_CLOCK_SKEW, 278 MII_KSZ9031_MOD_DATA_NO_POST_INC, 279 MBA6X_KSZ9031_CLK_SKEW); 280 281 phydev->drv->config(phydev); 282 283 return 0; 284 } 285 286 int board_eth_init(bd_t *bis) 287 { 288 uint32_t base = IMX_FEC_BASE; 289 struct mii_dev *bus = NULL; 290 struct phy_device *phydev = NULL; 291 int ret; 292 293 bus = fec_get_miibus(base, -1); 294 if (!bus) 295 return -EINVAL; 296 /* scan phy */ 297 phydev = phy_find_by_mask(bus, (0xf << CONFIG_FEC_MXC_PHYADDR), 298 PHY_INTERFACE_MODE_RGMII); 299 300 if (!phydev) { 301 ret = -EINVAL; 302 goto free_bus; 303 } 304 ret = fec_probe(bis, -1, base, bus, phydev); 305 if (ret) 306 goto free_phydev; 307 308 return 0; 309 310 free_phydev: 311 free(phydev); 312 free_bus: 313 free(bus); 314 return ret; 315 } 316 317 int tqma6_bb_board_early_init_f(void) 318 { 319 mba6_setup_iomuxc_uart(); 320 321 return 0; 322 } 323 324 int tqma6_bb_board_init(void) 325 { 326 mba6_setup_i2c(); 327 /* do it here - to have reset completed */ 328 mba6_setup_iomuxc_enet(); 329 330 return 0; 331 } 332 333 int tqma6_bb_board_late_init(void) 334 { 335 return 0; 336 } 337 338 const char *tqma6_bb_get_boardname(void) 339 { 340 return "MBa6x"; 341 } 342 343 /* 344 * Device Tree Support 345 */ 346 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) 347 void tqma6_bb_ft_board_setup(void *blob, bd_t *bd) 348 { 349 /* TBD */ 350 } 351 #endif /* defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) */ 352