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