1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * linux/arch/arm/mach-omap1/board-innovator.c
4 *
5 * Board specific inits for OMAP-1510 and OMAP-1610 Innovator
6 *
7 * Copyright (C) 2001 RidgeRun, Inc.
8 * Author: Greg Lonnon <glonnon@ridgerun.com>
9 *
10 * Copyright (C) 2002 MontaVista Software, Inc.
11 *
12 * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6
13 * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <tony@atomide.com>
14 */
15#include <linux/gpio.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/platform_device.h>
19#include <linux/delay.h>
20#include <linux/mtd/mtd.h>
21#include <linux/mtd/partitions.h>
22#include <linux/mtd/physmap.h>
23#include <linux/input.h>
24#include <linux/smc91x.h>
25#include <linux/omapfb.h>
26
27#include <asm/mach-types.h>
28#include <asm/mach/arch.h>
29#include <asm/mach/map.h>
30
31#include <mach/mux.h>
32#include "flash.h"
33#include <mach/tc.h>
34#include <linux/platform_data/keypad-omap.h>
35
36#include <mach/hardware.h>
37#include <mach/usb.h>
38
39#include "iomap.h"
40#include "common.h"
41#include "mmc.h"
42
43/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
44#define INNOVATOR1610_ETHR_START	0x04000300
45
46static const unsigned int innovator_keymap[] = {
47	KEY(0, 0, KEY_F1),
48	KEY(3, 0, KEY_DOWN),
49	KEY(1, 1, KEY_F2),
50	KEY(2, 1, KEY_RIGHT),
51	KEY(0, 2, KEY_F3),
52	KEY(1, 2, KEY_F4),
53	KEY(2, 2, KEY_UP),
54	KEY(2, 3, KEY_ENTER),
55	KEY(3, 3, KEY_LEFT),
56};
57
58static struct mtd_partition innovator_partitions[] = {
59	/* bootloader (U-Boot, etc) in first sector */
60	{
61	      .name		= "bootloader",
62	      .offset		= 0,
63	      .size		= SZ_128K,
64	      .mask_flags	= MTD_WRITEABLE, /* force read-only */
65	},
66	/* bootloader params in the next sector */
67	{
68	      .name		= "params",
69	      .offset		= MTDPART_OFS_APPEND,
70	      .size		= SZ_128K,
71	      .mask_flags	= 0,
72	},
73	/* kernel */
74	{
75	      .name		= "kernel",
76	      .offset		= MTDPART_OFS_APPEND,
77	      .size		= SZ_2M,
78	      .mask_flags	= 0
79	},
80	/* rest of flash1 is a file system */
81	{
82	      .name		= "rootfs",
83	      .offset		= MTDPART_OFS_APPEND,
84	      .size		= SZ_16M - SZ_2M - 2 * SZ_128K,
85	      .mask_flags	= 0
86	},
87	/* file system */
88	{
89	      .name		= "filesystem",
90	      .offset		= MTDPART_OFS_APPEND,
91	      .size		= MTDPART_SIZ_FULL,
92	      .mask_flags	= 0
93	}
94};
95
96static struct physmap_flash_data innovator_flash_data = {
97	.width		= 2,
98	.set_vpp	= omap1_set_vpp,
99	.parts		= innovator_partitions,
100	.nr_parts	= ARRAY_SIZE(innovator_partitions),
101};
102
103static struct resource innovator_flash_resource = {
104	.start		= OMAP_CS0_PHYS,
105	.end		= OMAP_CS0_PHYS + SZ_32M - 1,
106	.flags		= IORESOURCE_MEM,
107};
108
109static struct platform_device innovator_flash_device = {
110	.name		= "physmap-flash",
111	.id		= 0,
112	.dev		= {
113		.platform_data	= &innovator_flash_data,
114	},
115	.num_resources	= 1,
116	.resource	= &innovator_flash_resource,
117};
118
119static struct resource innovator_kp_resources[] = {
120	[0] = {
121		.start	= INT_KEYBOARD,
122		.end	= INT_KEYBOARD,
123		.flags	= IORESOURCE_IRQ,
124	},
125};
126
127static const struct matrix_keymap_data innovator_keymap_data = {
128	.keymap		= innovator_keymap,
129	.keymap_size	= ARRAY_SIZE(innovator_keymap),
130};
131
132static struct omap_kp_platform_data innovator_kp_data = {
133	.rows		= 8,
134	.cols		= 8,
135	.keymap_data	= &innovator_keymap_data,
136	.delay		= 4,
137};
138
139static struct platform_device innovator_kp_device = {
140	.name		= "omap-keypad",
141	.id		= -1,
142	.dev		= {
143		.platform_data = &innovator_kp_data,
144	},
145	.num_resources	= ARRAY_SIZE(innovator_kp_resources),
146	.resource	= innovator_kp_resources,
147};
148
149static struct smc91x_platdata innovator_smc91x_info = {
150	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT,
151	.leda	= RPC_LED_100_10,
152	.ledb	= RPC_LED_TX_RX,
153};
154
155#ifdef CONFIG_ARCH_OMAP15XX
156
157#include <linux/spi/spi.h>
158#include <linux/spi/ads7846.h>
159
160
161/* Only FPGA needs to be mapped here. All others are done with ioremap */
162static struct map_desc innovator1510_io_desc[] __initdata = {
163	{
164		.virtual	= OMAP1510_FPGA_BASE,
165		.pfn		= __phys_to_pfn(OMAP1510_FPGA_START),
166		.length		= OMAP1510_FPGA_SIZE,
167		.type		= MT_DEVICE
168	}
169};
170
171static struct resource innovator1510_smc91x_resources[] = {
172	[0] = {
173		.start	= OMAP1510_FPGA_ETHR_START,	/* Physical */
174		.end	= OMAP1510_FPGA_ETHR_START + 0xf,
175		.flags	= IORESOURCE_MEM,
176	},
177	[1] = {
178		.start	= OMAP1510_INT_ETHER,
179		.end	= OMAP1510_INT_ETHER,
180		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
181	},
182};
183
184static struct platform_device innovator1510_smc91x_device = {
185	.name		= "smc91x",
186	.id		= 0,
187	.dev	= {
188		.platform_data	= &innovator_smc91x_info,
189	},
190	.num_resources	= ARRAY_SIZE(innovator1510_smc91x_resources),
191	.resource	= innovator1510_smc91x_resources,
192};
193
194static struct platform_device innovator1510_lcd_device = {
195	.name		= "lcd_inn1510",
196	.id		= -1,
197};
198
199static struct platform_device innovator1510_spi_device = {
200	.name		= "spi_inn1510",
201	.id		= -1,
202};
203
204static struct platform_device *innovator1510_devices[] __initdata = {
205	&innovator_flash_device,
206	&innovator1510_smc91x_device,
207	&innovator_kp_device,
208	&innovator1510_lcd_device,
209	&innovator1510_spi_device,
210};
211
212static int innovator_get_pendown_state(void)
213{
214	return !(__raw_readb(OMAP1510_FPGA_TOUCHSCREEN) & (1 << 5));
215}
216
217static const struct ads7846_platform_data innovator1510_ts_info = {
218	.model			= 7846,
219	.vref_delay_usecs	= 100,	/* internal, no capacitor */
220	.x_plate_ohms		= 419,
221	.y_plate_ohms		= 486,
222	.get_pendown_state	= innovator_get_pendown_state,
223};
224
225static struct spi_board_info __initdata innovator1510_boardinfo[] = { {
226	/* FPGA (bus "10") CS0 has an ads7846e */
227	.modalias		= "ads7846",
228	.platform_data		= &innovator1510_ts_info,
229	.irq			= OMAP1510_INT_FPGA_TS,
230	.max_speed_hz		= 120000 /* max sample rate at 3V */
231					* 26 /* command + data + overhead */,
232	.bus_num		= 10,
233	.chip_select		= 0,
234} };
235
236#endif /* CONFIG_ARCH_OMAP15XX */
237
238#ifdef CONFIG_ARCH_OMAP16XX
239
240static struct resource innovator1610_smc91x_resources[] = {
241	[0] = {
242		.start	= INNOVATOR1610_ETHR_START,		/* Physical */
243		.end	= INNOVATOR1610_ETHR_START + 0xf,
244		.flags	= IORESOURCE_MEM,
245	},
246	[1] = {
247		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
248	},
249};
250
251static struct platform_device innovator1610_smc91x_device = {
252	.name		= "smc91x",
253	.id		= 0,
254	.dev	= {
255		.platform_data	= &innovator_smc91x_info,
256	},
257	.num_resources	= ARRAY_SIZE(innovator1610_smc91x_resources),
258	.resource	= innovator1610_smc91x_resources,
259};
260
261static struct platform_device innovator1610_lcd_device = {
262	.name		= "inn1610_lcd",
263	.id		= -1,
264};
265
266static struct platform_device *innovator1610_devices[] __initdata = {
267	&innovator_flash_device,
268	&innovator1610_smc91x_device,
269	&innovator_kp_device,
270	&innovator1610_lcd_device,
271};
272
273#endif /* CONFIG_ARCH_OMAP16XX */
274
275static void __init innovator_init_smc91x(void)
276{
277	if (cpu_is_omap1510()) {
278		__raw_writeb(__raw_readb(OMAP1510_FPGA_RST) & ~1,
279			   OMAP1510_FPGA_RST);
280		udelay(750);
281	} else {
282		if (gpio_request(0, "SMC91x irq") < 0) {
283			printk("Error requesting gpio 0 for smc91x irq\n");
284			return;
285		}
286	}
287}
288
289#ifdef CONFIG_ARCH_OMAP15XX
290static struct omap_usb_config innovator1510_usb_config __initdata = {
291	/* for bundled non-standard host and peripheral cables */
292	.hmc_mode	= 4,
293
294	.register_host	= 1,
295	.pins[1]	= 6,
296	.pins[2]	= 6,		/* Conflicts with UART2 */
297
298	.register_dev	= 1,
299	.pins[0]	= 2,
300};
301
302static const struct omap_lcd_config innovator1510_lcd_config __initconst = {
303	.ctrl_name	= "internal",
304};
305#endif
306
307#ifdef CONFIG_ARCH_OMAP16XX
308static struct omap_usb_config h2_usb_config __initdata = {
309	/* usb1 has a Mini-AB port and external isp1301 transceiver */
310	.otg		= 2,
311
312#if IS_ENABLED(CONFIG_USB_OMAP)
313	.hmc_mode	= 19,	/* 0:host(off) 1:dev|otg 2:disabled */
314	/* .hmc_mode	= 21,*/	/* 0:host(off) 1:dev(loopback) 2:host(loopback) */
315#elif	IS_ENABLED(CONFIG_USB_OHCI_HCD)
316	/* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
317	.hmc_mode	= 20,	/* 1:dev|otg(off) 1:host 2:disabled */
318#endif
319
320	.pins[1]	= 3,
321};
322
323static const struct omap_lcd_config innovator1610_lcd_config __initconst = {
324	.ctrl_name	= "internal",
325};
326#endif
327
328#if IS_ENABLED(CONFIG_MMC_OMAP)
329
330static int mmc_set_power(struct device *dev, int slot, int power_on,
331				int vdd)
332{
333	if (power_on)
334		__raw_writeb(__raw_readb(OMAP1510_FPGA_POWER) | (1 << 3),
335				OMAP1510_FPGA_POWER);
336	else
337		__raw_writeb(__raw_readb(OMAP1510_FPGA_POWER) & ~(1 << 3),
338				OMAP1510_FPGA_POWER);
339
340	return 0;
341}
342
343/*
344 * Innovator could use the following functions tested:
345 * - mmc_get_wp that uses OMAP_MPUIO(3)
346 * - mmc_get_cover_state that uses FPGA F4 UIO43
347 */
348static struct omap_mmc_platform_data mmc1_data = {
349	.nr_slots                       = 1,
350	.slots[0]       = {
351		.set_power		= mmc_set_power,
352		.wires			= 4,
353		.name                   = "mmcblk",
354	},
355};
356
357static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];
358
359static void __init innovator_mmc_init(void)
360{
361	mmc_data[0] = &mmc1_data;
362	omap1_init_mmc(mmc_data, OMAP15XX_NR_MMC);
363}
364
365#else
366static inline void innovator_mmc_init(void)
367{
368}
369#endif
370
371static void __init innovator_init(void)
372{
373	if (cpu_is_omap1510())
374		omap1510_fpga_init_irq();
375	innovator_init_smc91x();
376
377#ifdef CONFIG_ARCH_OMAP15XX
378	if (cpu_is_omap1510()) {
379		unsigned char reg;
380
381		/* mux pins for uarts */
382		omap_cfg_reg(UART1_TX);
383		omap_cfg_reg(UART1_RTS);
384		omap_cfg_reg(UART2_TX);
385		omap_cfg_reg(UART2_RTS);
386		omap_cfg_reg(UART3_TX);
387		omap_cfg_reg(UART3_RX);
388
389		reg = __raw_readb(OMAP1510_FPGA_POWER);
390		reg |= OMAP1510_FPGA_PCR_COM1_EN;
391		__raw_writeb(reg, OMAP1510_FPGA_POWER);
392		udelay(10);
393
394		reg = __raw_readb(OMAP1510_FPGA_POWER);
395		reg |= OMAP1510_FPGA_PCR_COM2_EN;
396		__raw_writeb(reg, OMAP1510_FPGA_POWER);
397		udelay(10);
398
399		platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices));
400		spi_register_board_info(innovator1510_boardinfo,
401				ARRAY_SIZE(innovator1510_boardinfo));
402	}
403#endif
404#ifdef CONFIG_ARCH_OMAP16XX
405	if (!cpu_is_omap1510()) {
406		innovator1610_smc91x_resources[1].start = gpio_to_irq(0);
407		innovator1610_smc91x_resources[1].end = gpio_to_irq(0);
408		platform_add_devices(innovator1610_devices, ARRAY_SIZE(innovator1610_devices));
409	}
410#endif
411
412#ifdef CONFIG_ARCH_OMAP15XX
413	if (cpu_is_omap1510()) {
414		omap1_usb_init(&innovator1510_usb_config);
415		omapfb_set_lcd_config(&innovator1510_lcd_config);
416	}
417#endif
418#ifdef CONFIG_ARCH_OMAP16XX
419	if (cpu_is_omap1610()) {
420		omap1_usb_init(&h2_usb_config);
421		omapfb_set_lcd_config(&innovator1610_lcd_config);
422	}
423#endif
424	omap_serial_init();
425	omap_register_i2c_bus(1, 100, NULL, 0);
426	innovator_mmc_init();
427}
428
429/*
430 * REVISIT: Assume 15xx for now, we don't want to do revision check
431 * until later on. The right way to fix this is to set up a different
432 * machine_id for 16xx Innovator, or use device tree.
433 */
434static void __init innovator_map_io(void)
435{
436#ifdef CONFIG_ARCH_OMAP15XX
437	omap15xx_map_io();
438
439	iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
440	udelay(10);	/* Delay needed for FPGA */
441
442	/* Dump the Innovator FPGA rev early - useful info for support. */
443	pr_debug("Innovator FPGA Rev %d.%d Board Rev %d\n",
444			__raw_readb(OMAP1510_FPGA_REV_HIGH),
445			__raw_readb(OMAP1510_FPGA_REV_LOW),
446			__raw_readb(OMAP1510_FPGA_BOARD_REV));
447#endif
448}
449
450MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
451	/* Maintainer: MontaVista Software, Inc. */
452	.atag_offset	= 0x100,
453	.map_io		= innovator_map_io,
454	.init_early     = omap1_init_early,
455	.init_irq	= omap1_init_irq,
456	.handle_irq	= omap1_handle_irq,
457	.init_machine	= innovator_init,
458	.init_late	= omap1_init_late,
459	.init_time	= omap1_timer_init,
460	.restart	= omap1_restart,
461MACHINE_END
462