1/*
2 * arch/arm/mach-ep93xx/ts72xx.c
3 * Technologic Systems TS72xx SBC support.
4 *
5 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or (at
10 * your option) any later version.
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/mm.h>
16#include <linux/sched.h>
17#include <linux/interrupt.h>
18#include <linux/ioport.h>
19#include <linux/mtd/physmap.h>
20#include <linux/platform_device.h>
21#include <linux/m48t86.h>
22#include <asm/io.h>
23#include <asm/hardware.h>
24#include <asm/mach-types.h>
25#include <asm/mach/arch.h>
26#include <asm/mach/map.h>
27
28static struct map_desc ts72xx_io_desc[] __initdata = {
29	{
30		.virtual	= TS72XX_MODEL_VIRT_BASE,
31		.pfn		= __phys_to_pfn(TS72XX_MODEL_PHYS_BASE),
32		.length		= TS72XX_MODEL_SIZE,
33		.type		= MT_DEVICE,
34	}, {
35		.virtual	= TS72XX_OPTIONS_VIRT_BASE,
36		.pfn		= __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE),
37		.length		= TS72XX_OPTIONS_SIZE,
38		.type		= MT_DEVICE,
39	}, {
40		.virtual	= TS72XX_OPTIONS2_VIRT_BASE,
41		.pfn		= __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
42		.length		= TS72XX_OPTIONS2_SIZE,
43		.type		= MT_DEVICE,
44	}, {
45		.virtual	= TS72XX_RTC_INDEX_VIRT_BASE,
46		.pfn		= __phys_to_pfn(TS72XX_RTC_INDEX_PHYS_BASE),
47		.length		= TS72XX_RTC_INDEX_SIZE,
48		.type		= MT_DEVICE,
49	}, {
50		.virtual	= TS72XX_RTC_DATA_VIRT_BASE,
51		.pfn		= __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE),
52		.length		= TS72XX_RTC_DATA_SIZE,
53		.type		= MT_DEVICE,
54	}
55};
56
57static struct map_desc ts72xx_nand_io_desc[] __initdata = {
58	{
59		.virtual	= TS72XX_NAND_DATA_VIRT_BASE,
60		.pfn		= __phys_to_pfn(TS72XX_NAND1_DATA_PHYS_BASE),
61		.length		= TS72XX_NAND_DATA_SIZE,
62		.type		= MT_DEVICE,
63	}, {
64		.virtual	= TS72XX_NAND_CONTROL_VIRT_BASE,
65		.pfn		= __phys_to_pfn(TS72XX_NAND1_CONTROL_PHYS_BASE),
66		.length		= TS72XX_NAND_CONTROL_SIZE,
67		.type		= MT_DEVICE,
68	}, {
69		.virtual	= TS72XX_NAND_BUSY_VIRT_BASE,
70		.pfn		= __phys_to_pfn(TS72XX_NAND1_BUSY_PHYS_BASE),
71		.length		= TS72XX_NAND_BUSY_SIZE,
72		.type		= MT_DEVICE,
73	}
74};
75
76static struct map_desc ts72xx_alternate_nand_io_desc[] __initdata = {
77	{
78		.virtual	= TS72XX_NAND_DATA_VIRT_BASE,
79		.pfn		= __phys_to_pfn(TS72XX_NAND2_DATA_PHYS_BASE),
80		.length		= TS72XX_NAND_DATA_SIZE,
81		.type		= MT_DEVICE,
82	}, {
83		.virtual	= TS72XX_NAND_CONTROL_VIRT_BASE,
84		.pfn		= __phys_to_pfn(TS72XX_NAND2_CONTROL_PHYS_BASE),
85		.length		= TS72XX_NAND_CONTROL_SIZE,
86		.type		= MT_DEVICE,
87	}, {
88		.virtual	= TS72XX_NAND_BUSY_VIRT_BASE,
89		.pfn		= __phys_to_pfn(TS72XX_NAND2_BUSY_PHYS_BASE),
90		.length		= TS72XX_NAND_BUSY_SIZE,
91		.type		= MT_DEVICE,
92	}
93};
94
95static void __init ts72xx_map_io(void)
96{
97	ep93xx_map_io();
98	iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc));
99
100	/*
101	 * The TS-7200 has NOR flash, the other models have NAND flash.
102	 */
103	if (!board_is_ts7200()) {
104		if (is_ts9420_installed()) {
105			iotable_init(ts72xx_alternate_nand_io_desc,
106				ARRAY_SIZE(ts72xx_alternate_nand_io_desc));
107		} else {
108			iotable_init(ts72xx_nand_io_desc,
109				ARRAY_SIZE(ts72xx_nand_io_desc));
110		}
111	}
112}
113
114static struct physmap_flash_data ts72xx_flash_data = {
115	.width		= 1,
116};
117
118static struct resource ts72xx_flash_resource = {
119	.start		= TS72XX_NOR_PHYS_BASE,
120	.end		= TS72XX_NOR_PHYS_BASE + 0x00ffffff,
121	.flags		= IORESOURCE_MEM,
122};
123
124static struct platform_device ts72xx_flash = {
125	.name		= "physmap-flash",
126	.id		= 0,
127	.dev		= {
128		.platform_data	= &ts72xx_flash_data,
129	},
130	.num_resources	= 1,
131	.resource	= &ts72xx_flash_resource,
132};
133
134static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
135{
136	__raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
137	return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE);
138}
139
140static void ts72xx_rtc_writebyte(unsigned char value, unsigned long addr)
141{
142	__raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
143	__raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE);
144}
145
146static struct m48t86_ops ts72xx_rtc_ops = {
147	.readbyte		= ts72xx_rtc_readbyte,
148	.writebyte		= ts72xx_rtc_writebyte,
149};
150
151static struct platform_device ts72xx_rtc_device = {
152	.name			= "rtc-m48t86",
153	.id			= -1,
154	.dev			= {
155		.platform_data		= &ts72xx_rtc_ops,
156	},
157	.num_resources		= 0,
158};
159
160static struct ep93xx_eth_data ts72xx_eth_data = {
161	.phy_id			= 1,
162};
163
164static struct resource ts72xx_eth_resource[] = {
165	{
166		.start	= EP93XX_ETHERNET_PHYS_BASE,
167		.end	= EP93XX_ETHERNET_PHYS_BASE + 0xffff,
168		.flags	= IORESOURCE_MEM,
169	}, {
170		.start	= IRQ_EP93XX_ETHERNET,
171		.end	= IRQ_EP93XX_ETHERNET,
172		.flags	= IORESOURCE_IRQ,
173	}
174};
175
176static struct platform_device ts72xx_eth_device = {
177	.name		= "ep93xx-eth",
178	.id		= -1,
179	.dev		= {
180		.platform_data	= &ts72xx_eth_data,
181	},
182	.num_resources	= 2,
183	.resource	= ts72xx_eth_resource,
184};
185
186static void __init ts72xx_init_machine(void)
187{
188	ep93xx_init_devices();
189	if (board_is_ts7200())
190		platform_device_register(&ts72xx_flash);
191	platform_device_register(&ts72xx_rtc_device);
192
193	memcpy(ts72xx_eth_data.dev_addr,
194		(void *)(EP93XX_ETHERNET_BASE + 0x50), 6);
195	platform_device_register(&ts72xx_eth_device);
196}
197
198MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
199	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
200	.phys_io	= EP93XX_APB_PHYS_BASE,
201	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
202	.boot_params	= 0x00000100,
203	.map_io		= ts72xx_map_io,
204	.init_irq	= ep93xx_init_irq,
205	.timer		= &ep93xx_timer,
206	.init_machine	= ts72xx_init_machine,
207MACHINE_END
208