1/* 2 * @TAG(OTHER_GPL) 3 */ 4 5/* 6 * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. 7 * Copyright (C) 2018 NXP 8 * 9 * See file CREDITS for list of people who contributed to this 10 * project. 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License as 14 * published by the Free Software Foundation; either version 2 of 15 * the License, or (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 25 * MA 02111-1307 USA 26 */ 27 28/* 29 * u-boot-imx6/board/freescale/mx6qsabrelite/mx6qsabrelite.c 30 */ 31 32#include "common.h" 33#include "../io.h" 34#include "imx-regs.h" 35#include <errno.h> 36 37#include "gpio.h" 38#include "mx6x_pins.h" 39#include "imx8mq_pins.h" 40#include "miiphy.h" 41#include "micrel.h" 42#include "mx6qsabrelite.h" 43#include <assert.h> 44#include <utils/util.h> 45#include <platsupport/io.h> 46 47#include <stdio.h> 48 49#ifdef CONFIG_PLAT_IMX6 50#define IOMUXC_PADDR 0x020E0000 51#define IOMUXC_SIZE 0x4000 52#endif 53#ifdef CONFIG_PLAT_IMX8MQ_EVK 54#define IOMUXC_PADDR 0x30330000 55#define IOMUXC_SIZE 0x10000 56#endif 57 58#define ENET_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ 59 PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ 60 PAD_CTL_DSE_40ohm | PAD_CTL_HYS) 61 62static iomux_v3_cfg_t const enet_pads1[] = { 63 MX6Q_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL), 64 MX6Q_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), 65 MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL), 66 MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), 67 MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), 68 MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), 69 MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), 70 MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), 71 MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL), 72 /* pin 35 - 1 (PHY_AD2) on reset */ 73 MX6Q_PAD_RGMII_RXC__GPIO_6_30 | MUX_PAD_CTRL(NO_PAD_CTRL), 74 /* pin 32 - 1 - (MODE0) all */ 75 MX6Q_PAD_RGMII_RD0__GPIO_6_25 | MUX_PAD_CTRL(NO_PAD_CTRL), 76 /* pin 31 - 1 - (MODE1) all */ 77 MX6Q_PAD_RGMII_RD1__GPIO_6_27 | MUX_PAD_CTRL(NO_PAD_CTRL), 78 /* pin 28 - 1 - (MODE2) all */ 79 MX6Q_PAD_RGMII_RD2__GPIO_6_28 | MUX_PAD_CTRL(NO_PAD_CTRL), 80 /* pin 27 - 1 - (MODE3) all */ 81 MX6Q_PAD_RGMII_RD3__GPIO_6_29 | MUX_PAD_CTRL(NO_PAD_CTRL), 82 /* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */ 83 MX6Q_PAD_RGMII_RX_CTL__GPIO_6_24 | MUX_PAD_CTRL(NO_PAD_CTRL), 84 /* pin 42 PHY nRST */ 85 MX6Q_PAD_EIM_D23__GPIO_3_23 | MUX_PAD_CTRL(NO_PAD_CTRL), 86}; 87 88static iomux_v3_cfg_t const enet_pads2[] = { 89 MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL), 90 MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), 91 MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), 92 MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), 93 MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), 94 MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), 95}; 96 97static iomux_v3_cfg_t const fec1_pads[] = { 98 /* see the IMX8 reference manual for what the options mean, 99 * Section 8.2.4 i.e. IOMUXC_SW_PAD_CTL_PAD_* registers */ 100 IMX8MQ_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(0x3), 101 IMX8MQ_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(0x23), 102 IMX8MQ_PAD_ENET_TD3__ENET_RGMII_TD3 | MUX_PAD_CTRL(0x1f), 103 IMX8MQ_PAD_ENET_TD2__ENET_RGMII_TD2 | MUX_PAD_CTRL(0x1f), 104 IMX8MQ_PAD_ENET_TD1__ENET_RGMII_TD1 | MUX_PAD_CTRL(0x1f), 105 IMX8MQ_PAD_ENET_TD0__ENET_RGMII_TD0 | MUX_PAD_CTRL(0x1f), 106 IMX8MQ_PAD_ENET_RD3__ENET_RGMII_RD3 | MUX_PAD_CTRL(0x91), 107 IMX8MQ_PAD_ENET_RD2__ENET_RGMII_RD2 | MUX_PAD_CTRL(0x91), 108 IMX8MQ_PAD_ENET_RD1__ENET_RGMII_RD1 | MUX_PAD_CTRL(0x91), 109 IMX8MQ_PAD_ENET_RD0__ENET_RGMII_RD0 | MUX_PAD_CTRL(0x91), 110 IMX8MQ_PAD_ENET_TXC__ENET_RGMII_TXC | MUX_PAD_CTRL(0x1f), 111 IMX8MQ_PAD_ENET_RXC__ENET_RGMII_RXC | MUX_PAD_CTRL(0x91), 112 IMX8MQ_PAD_ENET_TX_CTL__ENET_RGMII_TX_CTL | MUX_PAD_CTRL(0x1f), 113 IMX8MQ_PAD_ENET_RX_CTL__ENET_RGMII_RX_CTL | MUX_PAD_CTRL(0x91), 114 IMX8MQ_PAD_GPIO1_IO09__GPIO1_IO9 | MUX_PAD_CTRL(0x19) 115}; 116 117/* 118 * configures a single pad in the iomuxer 119 */ 120static int imx_iomux_v3_setup_pad(void *base, iomux_v3_cfg_t pad) 121{ 122 uint32_t mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT; 123 uint32_t mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT; 124 uint32_t sel_input_ofs = (pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT; 125 uint32_t sel_input = (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT; 126 uint32_t pad_ctrl_ofs = (pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT; 127 uint32_t pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT; 128 129 if (mux_ctrl_ofs) { 130 __raw_writel(mux_mode, base + mux_ctrl_ofs); 131 } 132 133 if (sel_input_ofs) { 134 __raw_writel(sel_input, base + sel_input_ofs); 135 } 136 137 if (!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs) { 138 __raw_writel(pad_ctrl, base + pad_ctrl_ofs); 139 } 140 141 return 0; 142} 143 144static int imx_iomux_v3_setup_multiple_pads(void *base, iomux_v3_cfg_t const *pad_list, 145 unsigned count) 146{ 147 iomux_v3_cfg_t const *p = pad_list; 148 int i; 149 int ret; 150 151 for (i = 0; i < count; i++) { 152 ret = imx_iomux_v3_setup_pad(base, *p); 153 if (ret) { 154 return ret; 155 } 156 p++; 157 } 158 return 0; 159} 160 161int setup_iomux_enet(ps_io_ops_t *io_ops) 162{ 163 int ret; 164 void *base; 165 int unmapOnExit = 0; 166 167 if (mux_sys_valid(&io_ops->mux_sys)) { 168 base = mux_sys_get_vaddr(&io_ops->mux_sys); 169 } else { 170 base = RESOURCE(&io_ops->io_mapper, IOMUXC); 171 unmapOnExit = 1; 172 } 173 if (!base) { 174 return 1; 175 } 176 177 if (config_set(CONFIG_PLAT_IMX8MQ_EVK)) { 178 ret = imx_iomux_v3_setup_multiple_pads(base, fec1_pads, ARRAY_SIZE(fec1_pads)); 179 if (ret) { 180 return ret; 181 } 182 gpio_direction_output(IMX_GPIO_NR(1, 9), 0, io_ops); 183 udelay(500); 184 gpio_direction_output(IMX_GPIO_NR(1, 9), 1, io_ops); 185 186 uint32_t *gpr1 = base + 0x4; 187 // Change ENET_TX to use internal clocks and not the external clocks 188 *gpr1 = *gpr1 & ~(BIT(17) | BIT(13)); 189 } else if (config_set(CONFIG_PLAT_IMX6)) { 190 gpio_direction_output(IMX_GPIO_NR(3, 23), 0, io_ops); 191 gpio_direction_output(IMX_GPIO_NR(6, 30), 1, io_ops); 192 gpio_direction_output(IMX_GPIO_NR(6, 25), 1, io_ops); 193 gpio_direction_output(IMX_GPIO_NR(6, 27), 1, io_ops); 194 gpio_direction_output(IMX_GPIO_NR(6, 28), 1, io_ops); 195 gpio_direction_output(IMX_GPIO_NR(6, 29), 1, io_ops); 196 ret = imx_iomux_v3_setup_multiple_pads(base, enet_pads1, ARRAY_SIZE(enet_pads1)); 197 if (ret) { 198 return ret; 199 } 200 gpio_direction_output(IMX_GPIO_NR(6, 24), 1, io_ops); 201 /* Need delay 10ms according to KSZ9021 spec */ 202 udelay(1000 * 10); 203 gpio_set_value(IMX_GPIO_NR(3, 23), 1); 204 205 ret = imx_iomux_v3_setup_multiple_pads(base, enet_pads2, ARRAY_SIZE(enet_pads2)); 206 if (ret) { 207 return ret; 208 } 209 } 210 211 if (unmapOnExit) { 212 UNRESOURCE(&io_ops->io_mapper, IOMUXC, base); 213 } 214 return 0; 215} 216