1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Copyright (C) 2009 Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com>
4  */
5 
6 #include <linux/types.h>
7 #include <linux/init.h>
8 #include <linux/kernel.h>
9 #include <linux/memory.h>
10 #include <linux/platform_device.h>
11 #include <linux/mtd/physmap.h>
12 #include <linux/mtd/platnand.h>
13 #include <linux/gpio.h>
14 
15 #include <asm/mach-types.h>
16 #include <asm/mach/arch.h>
17 #include <asm/mach/time.h>
18 #include <asm/mach/map.h>
19 #include <asm/page.h>
20 #include <asm/setup.h>
21 
22 #include "common.h"
23 #include "devices-imx31.h"
24 #include "hardware.h"
25 #include "iomux-mx3.h"
26 
27 /* FPGA defines */
28 #define QONG_FPGA_VERSION(major, minor, rev)	\
29 	(((major & 0xF) << 12) | ((minor & 0xF) << 8) | (rev & 0xFF))
30 
31 #define QONG_FPGA_BASEADDR		MX31_CS1_BASE_ADDR
32 #define QONG_FPGA_PERIPH_SIZE		(1 << 24)
33 
34 #define QONG_FPGA_CTRL_BASEADDR		QONG_FPGA_BASEADDR
35 #define QONG_FPGA_CTRL_SIZE		0x10
36 /* FPGA control registers */
37 #define QONG_FPGA_CTRL_VERSION		0x00
38 
39 #define QONG_DNET_ID		1
40 #define QONG_DNET_BASEADDR	\
41 	(QONG_FPGA_BASEADDR + QONG_DNET_ID * QONG_FPGA_PERIPH_SIZE)
42 #define QONG_DNET_SIZE		0x00001000
43 
44 static const struct imxuart_platform_data uart_pdata __initconst = {
45 	.flags = IMXUART_HAVE_RTSCTS,
46 };
47 
48 static int uart_pins[] = {
49 	MX31_PIN_CTS1__CTS1,
50 	MX31_PIN_RTS1__RTS1,
51 	MX31_PIN_TXD1__TXD1,
52 	MX31_PIN_RXD1__RXD1
53 };
54 
mxc_init_imx_uart(void)55 static inline void __init mxc_init_imx_uart(void)
56 {
57 	mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins),
58 			"uart-0");
59 	imx31_add_imx_uart0(&uart_pdata);
60 }
61 
62 static struct resource dnet_resources[] = {
63 	{
64 		.name	= "dnet-memory",
65 		.start	= QONG_DNET_BASEADDR,
66 		.end	= QONG_DNET_BASEADDR + QONG_DNET_SIZE - 1,
67 		.flags	= IORESOURCE_MEM,
68 	}, {
69 		/* irq number is run-time assigned */
70 		.flags	= IORESOURCE_IRQ,
71 	},
72 };
73 
74 static struct platform_device dnet_device = {
75 	.name			= "dnet",
76 	.id			= -1,
77 	.num_resources		= ARRAY_SIZE(dnet_resources),
78 	.resource		= dnet_resources,
79 };
80 
qong_init_dnet(void)81 static int __init qong_init_dnet(void)
82 {
83 	int ret;
84 
85 	dnet_resources[1].start =
86 		gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1));
87 	dnet_resources[1].end =
88 		gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1));
89 	ret = platform_device_register(&dnet_device);
90 	return ret;
91 }
92 
93 /* MTD NOR flash */
94 
95 static struct physmap_flash_data qong_flash_data = {
96 	.width = 2,
97 };
98 
99 static struct resource qong_flash_resource = {
100 	.start = MX31_CS0_BASE_ADDR,
101 	.end = MX31_CS0_BASE_ADDR + SZ_128M - 1,
102 	.flags = IORESOURCE_MEM,
103 };
104 
105 static struct platform_device qong_nor_mtd_device = {
106 	.name = "physmap-flash",
107 	.id = 0,
108 	.dev = {
109 		.platform_data = &qong_flash_data,
110 		},
111 	.resource = &qong_flash_resource,
112 	.num_resources = 1,
113 };
114 
qong_init_nor_mtd(void)115 static void qong_init_nor_mtd(void)
116 {
117 	(void)platform_device_register(&qong_nor_mtd_device);
118 }
119 
120 /*
121  * Hardware specific access to control-lines
122  */
qong_nand_cmd_ctrl(struct nand_chip * nand_chip,int cmd,unsigned int ctrl)123 static void qong_nand_cmd_ctrl(struct nand_chip *nand_chip, int cmd,
124 			       unsigned int ctrl)
125 {
126 	if (cmd == NAND_CMD_NONE)
127 		return;
128 
129 	if (ctrl & NAND_CLE)
130 		writeb(cmd, nand_chip->legacy.IO_ADDR_W + (1 << 24));
131 	else
132 		writeb(cmd, nand_chip->legacy.IO_ADDR_W + (1 << 23));
133 }
134 
135 /*
136  * Read the Device Ready pin.
137  */
qong_nand_device_ready(struct nand_chip * chip)138 static int qong_nand_device_ready(struct nand_chip *chip)
139 {
140 	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_NFRB));
141 }
142 
qong_nand_select_chip(struct nand_chip * chip,int cs)143 static void qong_nand_select_chip(struct nand_chip *chip, int cs)
144 {
145 	if (cs >= 0)
146 		gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0);
147 	else
148 		gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 1);
149 }
150 
151 static struct platform_nand_data qong_nand_data = {
152 	.chip = {
153 		.nr_chips		= 1,
154 		.chip_delay		= 20,
155 		.options		= 0,
156 	},
157 	.ctrl = {
158 		.cmd_ctrl		= qong_nand_cmd_ctrl,
159 		.dev_ready		= qong_nand_device_ready,
160 		.select_chip		= qong_nand_select_chip,
161 	}
162 };
163 
164 static struct resource qong_nand_resource = {
165 	.start		= MX31_CS3_BASE_ADDR,
166 	.end		= MX31_CS3_BASE_ADDR + SZ_32M - 1,
167 	.flags		= IORESOURCE_MEM,
168 };
169 
170 static struct platform_device qong_nand_device = {
171 	.name		= "gen_nand",
172 	.id		= -1,
173 	.dev		= {
174 		.platform_data = &qong_nand_data,
175 	},
176 	.num_resources	= 1,
177 	.resource	= &qong_nand_resource,
178 };
179 
qong_init_nand_mtd(void)180 static void __init qong_init_nand_mtd(void)
181 {
182 	/* init CS */
183 	imx_writel(0x00004f00, MX31_IO_ADDRESS(MX31_WEIM_CSCRxU(3)));
184 	imx_writel(0x20013b31, MX31_IO_ADDRESS(MX31_WEIM_CSCRxL(3)));
185 	imx_writel(0x00020800, MX31_IO_ADDRESS(MX31_WEIM_CSCRxA(3)));
186 
187 	mxc_iomux_set_gpr(MUX_SDCTL_CSD1_SEL, true);
188 
189 	/* enable pin */
190 	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFCE_B, IOMUX_CONFIG_GPIO));
191 	if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), "nand_enable"))
192 		gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0);
193 
194 	/* ready/busy pin */
195 	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFRB, IOMUX_CONFIG_GPIO));
196 	if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFRB), "nand_rdy"))
197 		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_NFRB));
198 
199 	/* write protect pin */
200 	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFWP_B, IOMUX_CONFIG_GPIO));
201 	if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFWP_B), "nand_wp"))
202 		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_NFWP_B));
203 
204 	platform_device_register(&qong_nand_device);
205 }
206 
qong_init_fpga(void)207 static void __init qong_init_fpga(void)
208 {
209 	void __iomem *regs;
210 	u32 fpga_ver;
211 
212 	regs = ioremap(QONG_FPGA_CTRL_BASEADDR, QONG_FPGA_CTRL_SIZE);
213 	if (!regs) {
214 		printk(KERN_ERR "%s: failed to map registers, aborting.\n",
215 				__func__);
216 		return;
217 	}
218 
219 	fpga_ver = readl(regs + QONG_FPGA_CTRL_VERSION);
220 	iounmap(regs);
221 	printk(KERN_INFO "Qong FPGA version %d.%d.%d\n",
222 			(fpga_ver & 0xF000) >> 12,
223 			(fpga_ver & 0x0F00) >> 8, fpga_ver & 0x00FF);
224 	if (fpga_ver < QONG_FPGA_VERSION(0, 8, 7)) {
225 		printk(KERN_ERR "qong: Unexpected FPGA version, FPGA-based "
226 				"devices won't be registered!\n");
227 		return;
228 	}
229 
230 	/* register FPGA-based devices */
231 	qong_init_nand_mtd();
232 	qong_init_dnet();
233 }
234 
235 /*
236  * Board specific initialization.
237  */
qong_init(void)238 static void __init qong_init(void)
239 {
240 	imx31_soc_init();
241 
242 	mxc_init_imx_uart();
243 	qong_init_nor_mtd();
244 	imx31_add_imx2_wdt();
245 }
246 
qong_timer_init(void)247 static void __init qong_timer_init(void)
248 {
249 	mx31_clocks_init(26000000);
250 }
251 
252 MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
253 	/* Maintainer: DENX Software Engineering GmbH */
254 	.atag_offset = 0x100,
255 	.map_io = mx31_map_io,
256 	.init_early = imx31_init_early,
257 	.init_irq = mx31_init_irq,
258 	.init_time	= qong_timer_init,
259 	.init_machine = qong_init,
260 	.init_late	= qong_init_fpga,
261 	.restart	= mxc_restart,
262 MACHINE_END
263