]>
Commit | Line | Data |
---|---|---|
cb07d74e MN |
1 | /* |
2 | * Copyright (C) 2012 Freescale Semiconductor, Inc. | |
3 | * Author: Fabio Estevam <fabio.estevam@freescale.com> | |
4 | * | |
5 | * Copyright (C) 2013, 2014 TQ Systems (ported SabreSD to TQMa6x) | |
6 | * Author: Markus Niebel <markus.niebel@tq-group.com> | |
7 | * | |
8 | * SPDX-License-Identifier: GPL-2.0+ | |
9 | */ | |
10 | ||
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> | |
1221ce45 | 16 | #include <linux/errno.h> |
cb07d74e MN |
17 | #include <asm/gpio.h> |
18 | #include <asm/io.h> | |
552a848e SB |
19 | #include <asm/mach-imx/mxc_i2c.h> |
20 | #include <asm/mach-imx/spi.h> | |
cb07d74e MN |
21 | #include <common.h> |
22 | #include <fsl_esdhc.h> | |
23 | #include <libfdt.h> | |
24 | #include <i2c.h> | |
25 | #include <mmc.h> | |
26 | #include <power/pfuze100_pmic.h> | |
27 | #include <power/pmic.h> | |
8b8ca0d7 | 28 | #include <spi_flash.h> |
cb07d74e MN |
29 | |
30 | #include "tqma6_bb.h" | |
31 | ||
32 | DECLARE_GLOBAL_DATA_PTR; | |
33 | ||
34 | #define USDHC_CLK_PAD_CTRL (PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ | |
35 | PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) | |
36 | ||
37 | #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ | |
38 | PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) | |
39 | ||
40 | #define GPIO_OUT_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW | \ | |
41 | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) | |
42 | ||
43 | #define GPIO_IN_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW | \ | |
44 | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) | |
45 | ||
46 | #define SPI_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ | |
47 | PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) | |
48 | ||
49 | #define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ | |
03cfff0e | 50 | PAD_CTL_DSE_80ohm | PAD_CTL_HYS | \ |
cb07d74e MN |
51 | PAD_CTL_ODE | PAD_CTL_SRE_FAST) |
52 | ||
53 | int dram_init(void) | |
54 | { | |
b6d7810e | 55 | gd->ram_size = imx_ddr_size(); |
cb07d74e MN |
56 | |
57 | return 0; | |
58 | } | |
59 | ||
60 | static const uint16_t tqma6_emmc_dsr = 0x0100; | |
61 | ||
62 | /* eMMC on USDHCI3 always present */ | |
63 | static iomux_v3_cfg_t const tqma6_usdhc3_pads[] = { | |
64 | NEW_PAD_CTRL(MX6_PAD_SD3_CLK__SD3_CLK, USDHC_PAD_CTRL), | |
65 | NEW_PAD_CTRL(MX6_PAD_SD3_CMD__SD3_CMD, USDHC_PAD_CTRL), | |
66 | NEW_PAD_CTRL(MX6_PAD_SD3_DAT0__SD3_DATA0, USDHC_PAD_CTRL), | |
67 | NEW_PAD_CTRL(MX6_PAD_SD3_DAT1__SD3_DATA1, USDHC_PAD_CTRL), | |
68 | NEW_PAD_CTRL(MX6_PAD_SD3_DAT2__SD3_DATA2, USDHC_PAD_CTRL), | |
69 | NEW_PAD_CTRL(MX6_PAD_SD3_DAT3__SD3_DATA3, USDHC_PAD_CTRL), | |
70 | NEW_PAD_CTRL(MX6_PAD_SD3_DAT4__SD3_DATA4, USDHC_PAD_CTRL), | |
71 | NEW_PAD_CTRL(MX6_PAD_SD3_DAT5__SD3_DATA5, USDHC_PAD_CTRL), | |
72 | NEW_PAD_CTRL(MX6_PAD_SD3_DAT6__SD3_DATA6, USDHC_PAD_CTRL), | |
73 | NEW_PAD_CTRL(MX6_PAD_SD3_DAT7__SD3_DATA7, USDHC_PAD_CTRL), | |
74 | /* eMMC reset */ | |
75 | NEW_PAD_CTRL(MX6_PAD_SD3_RST__SD3_RESET, GPIO_OUT_PAD_CTRL), | |
76 | }; | |
77 | ||
78 | /* | |
79 | * According to board_mmc_init() the following map is done: | |
a187559e | 80 | * (U-Boot device node) (Physical Port) |
cb07d74e MN |
81 | * mmc0 eMMC (SD3) on TQMa6 |
82 | * mmc1 .. n optional slots used on baseboard | |
83 | */ | |
84 | struct fsl_esdhc_cfg tqma6_usdhc_cfg = { | |
85 | .esdhc_base = USDHC3_BASE_ADDR, | |
86 | .max_bus_width = 8, | |
87 | }; | |
88 | ||
89 | int board_mmc_getcd(struct mmc *mmc) | |
90 | { | |
91 | struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; | |
92 | int ret = 0; | |
93 | ||
94 | if (cfg->esdhc_base == USDHC3_BASE_ADDR) | |
95 | /* eMMC/uSDHC3 is always present */ | |
96 | ret = 1; | |
97 | else | |
98 | ret = tqma6_bb_board_mmc_getcd(mmc); | |
99 | ||
100 | return ret; | |
101 | } | |
102 | ||
103 | int board_mmc_getwp(struct mmc *mmc) | |
104 | { | |
105 | struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; | |
106 | int ret = 0; | |
107 | ||
108 | if (cfg->esdhc_base == USDHC3_BASE_ADDR) | |
109 | /* eMMC/uSDHC3 is always present */ | |
110 | ret = 0; | |
111 | else | |
112 | ret = tqma6_bb_board_mmc_getwp(mmc); | |
113 | ||
114 | return ret; | |
115 | } | |
116 | ||
117 | int board_mmc_init(bd_t *bis) | |
118 | { | |
119 | imx_iomux_v3_setup_multiple_pads(tqma6_usdhc3_pads, | |
120 | ARRAY_SIZE(tqma6_usdhc3_pads)); | |
121 | tqma6_usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); | |
122 | if (fsl_esdhc_initialize(bis, &tqma6_usdhc_cfg)) { | |
123 | puts("Warning: failed to initialize eMMC dev\n"); | |
124 | } else { | |
125 | struct mmc *mmc = find_mmc_device(0); | |
126 | if (mmc) | |
127 | mmc_set_dsr(mmc, tqma6_emmc_dsr); | |
128 | } | |
129 | ||
130 | tqma6_bb_board_mmc_init(bis); | |
131 | ||
132 | return 0; | |
133 | } | |
134 | ||
135 | static iomux_v3_cfg_t const tqma6_ecspi1_pads[] = { | |
136 | /* SS1 */ | |
137 | NEW_PAD_CTRL(MX6_PAD_EIM_D19__GPIO3_IO19, SPI_PAD_CTRL), | |
138 | NEW_PAD_CTRL(MX6_PAD_EIM_D16__ECSPI1_SCLK, SPI_PAD_CTRL), | |
139 | NEW_PAD_CTRL(MX6_PAD_EIM_D17__ECSPI1_MISO, SPI_PAD_CTRL), | |
140 | NEW_PAD_CTRL(MX6_PAD_EIM_D18__ECSPI1_MOSI, SPI_PAD_CTRL), | |
141 | }; | |
142 | ||
1719d49c MN |
143 | #define TQMA6_SF_CS_GPIO IMX_GPIO_NR(3, 19) |
144 | ||
cb07d74e | 145 | static unsigned const tqma6_ecspi1_cs[] = { |
1719d49c | 146 | TQMA6_SF_CS_GPIO, |
cb07d74e MN |
147 | }; |
148 | ||
34ee786e | 149 | __weak void tqma6_iomuxc_spi(void) |
cb07d74e MN |
150 | { |
151 | unsigned i; | |
152 | ||
153 | for (i = 0; i < ARRAY_SIZE(tqma6_ecspi1_cs); ++i) | |
154 | gpio_direction_output(tqma6_ecspi1_cs[i], 1); | |
155 | imx_iomux_v3_setup_multiple_pads(tqma6_ecspi1_pads, | |
156 | ARRAY_SIZE(tqma6_ecspi1_pads)); | |
157 | } | |
158 | ||
1719d49c MN |
159 | int board_spi_cs_gpio(unsigned bus, unsigned cs) |
160 | { | |
161 | return ((bus == CONFIG_SF_DEFAULT_BUS) && | |
162 | (cs == CONFIG_SF_DEFAULT_CS)) ? TQMA6_SF_CS_GPIO : -1; | |
163 | } | |
164 | ||
cb07d74e MN |
165 | static struct i2c_pads_info tqma6_i2c3_pads = { |
166 | /* I2C3: on board LM75, M24C64, */ | |
167 | .scl = { | |
168 | .i2c_mode = NEW_PAD_CTRL(MX6_PAD_GPIO_5__I2C3_SCL, | |
169 | I2C_PAD_CTRL), | |
170 | .gpio_mode = NEW_PAD_CTRL(MX6_PAD_GPIO_5__GPIO1_IO05, | |
171 | I2C_PAD_CTRL), | |
172 | .gp = IMX_GPIO_NR(1, 5) | |
173 | }, | |
174 | .sda = { | |
175 | .i2c_mode = NEW_PAD_CTRL(MX6_PAD_GPIO_6__I2C3_SDA, | |
176 | I2C_PAD_CTRL), | |
177 | .gpio_mode = NEW_PAD_CTRL(MX6_PAD_GPIO_6__GPIO1_IO06, | |
178 | I2C_PAD_CTRL), | |
179 | .gp = IMX_GPIO_NR(1, 6) | |
180 | } | |
181 | }; | |
182 | ||
183 | static void tqma6_setup_i2c(void) | |
184 | { | |
fd53ec5b MN |
185 | int ret; |
186 | /* | |
187 | * use logical index for bus, e.g. I2C1 -> 0 | |
188 | * warn on error | |
189 | */ | |
190 | ret = setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &tqma6_i2c3_pads); | |
191 | if (ret) | |
192 | printf("setup I2C3 failed: %d\n", ret); | |
cb07d74e MN |
193 | } |
194 | ||
195 | int board_early_init_f(void) | |
196 | { | |
197 | return tqma6_bb_board_early_init_f(); | |
198 | } | |
199 | ||
200 | int board_init(void) | |
201 | { | |
202 | /* address of boot parameters */ | |
203 | gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; | |
204 | ||
205 | tqma6_iomuxc_spi(); | |
206 | tqma6_setup_i2c(); | |
207 | ||
208 | tqma6_bb_board_init(); | |
209 | ||
210 | return 0; | |
211 | } | |
212 | ||
213 | static const char *tqma6_get_boardname(void) | |
214 | { | |
215 | u32 cpurev = get_cpu_rev(); | |
216 | ||
217 | switch ((cpurev & 0xFF000) >> 12) { | |
218 | case MXC_CPU_MX6SOLO: | |
219 | return "TQMa6S"; | |
220 | break; | |
221 | case MXC_CPU_MX6DL: | |
222 | return "TQMa6DL"; | |
223 | break; | |
224 | case MXC_CPU_MX6D: | |
225 | return "TQMa6D"; | |
226 | break; | |
227 | case MXC_CPU_MX6Q: | |
228 | return "TQMa6Q"; | |
229 | break; | |
230 | default: | |
231 | return "??"; | |
232 | }; | |
233 | } | |
234 | ||
d7d8e8e4 MN |
235 | /* setup board specific PMIC */ |
236 | int power_init_board(void) | |
cb07d74e MN |
237 | { |
238 | struct pmic *p; | |
d7d8e8e4 | 239 | u32 reg, rev; |
cb07d74e | 240 | |
cb07d74e | 241 | power_pfuze100_init(TQMA6_PFUZE100_I2C_BUS); |
676ac24e | 242 | p = pmic_get("PFUZE100"); |
cb07d74e MN |
243 | if (p && !pmic_probe(p)) { |
244 | pmic_reg_read(p, PFUZE100_DEVICEID, ®); | |
d7d8e8e4 MN |
245 | pmic_reg_read(p, PFUZE100_REVID, &rev); |
246 | printf("PMIC: PFUZE100 ID=0x%02x REV=0x%02x\n", reg, rev); | |
cb07d74e MN |
247 | } |
248 | ||
d7d8e8e4 MN |
249 | return 0; |
250 | } | |
251 | ||
252 | int board_late_init(void) | |
253 | { | |
254 | setenv("board_name", tqma6_get_boardname()); | |
255 | ||
cb07d74e MN |
256 | tqma6_bb_board_late_init(); |
257 | ||
258 | return 0; | |
259 | } | |
260 | ||
261 | int checkboard(void) | |
262 | { | |
263 | printf("Board: %s on a %s\n", tqma6_get_boardname(), | |
264 | tqma6_bb_get_boardname()); | |
265 | return 0; | |
266 | } | |
267 | ||
268 | /* | |
269 | * Device Tree Support | |
270 | */ | |
271 | #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) | |
468fb1e4 | 272 | #define MODELSTRLEN 32u |
e895a4b0 | 273 | int ft_board_setup(void *blob, bd_t *bd) |
cb07d74e | 274 | { |
468fb1e4 MN |
275 | char modelstr[MODELSTRLEN]; |
276 | ||
277 | snprintf(modelstr, MODELSTRLEN, "TQ %s on %s", tqma6_get_boardname(), | |
278 | tqma6_bb_get_boardname()); | |
279 | do_fixup_by_path_string(blob, "/", "model", modelstr); | |
280 | fdt_fixup_memory(blob, (u64)PHYS_SDRAM, (u64)gd->ram_size); | |
cb07d74e MN |
281 | /* bring in eMMC dsr settings */ |
282 | do_fixup_by_path_u32(blob, | |
283 | "/soc/aips-bus@02100000/usdhc@02198000", | |
284 | "dsr", tqma6_emmc_dsr, 2); | |
285 | tqma6_bb_ft_board_setup(blob, bd); | |
e895a4b0 SG |
286 | |
287 | return 0; | |
cb07d74e MN |
288 | } |
289 | #endif /* defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) */ |