1 /*
2  * arch/sh/boards/renesas/r7780rp/setup.c
3  *
4  * Renesas Solutions Highlander Support.
5  *
6  * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
7  * Copyright (C) 2005 - 2008 Paul Mundt
8  *
9  * This contains support for the R7780RP-1, R7780MP, and R7785RP
10  * Highlander modules.
11  *
12  * This file is subject to the terms and conditions of the GNU General Public
13  * License.  See the file "COPYING" in the main directory of this archive
14  * for more details.
15  */
16 #include <linux/init.h>
17 #include <linux/io.h>
18 #include <linux/platform_device.h>
19 #include <linux/ata_platform.h>
20 #include <linux/types.h>
21 #include <linux/mtd/physmap.h>
22 #include <linux/i2c.h>
23 #include <linux/irq.h>
24 #include <linux/interrupt.h>
25 #include <linux/usb/r8a66597.h>
26 #include <linux/usb/m66592.h>
27 #include <linux/clkdev.h>
28 #include <net/ax88796.h>
29 #include <asm/machvec.h>
30 #include <mach/highlander.h>
31 #include <asm/clock.h>
32 #include <asm/heartbeat.h>
33 #include <asm/io.h>
34 #include <asm/io_trapped.h>
35 
36 static struct r8a66597_platdata r8a66597_data = {
37 	.xtal = R8A66597_PLATDATA_XTAL_12MHZ,
38 	.vif = 1,
39 };
40 
41 static struct resource r8a66597_usb_host_resources[] = {
42 	[0] = {
43 		.start	= 0xA4200000,
44 		.end	= 0xA42000FF,
45 		.flags	= IORESOURCE_MEM,
46 	},
47 	[1] = {
48 		.start	= IRQ_EXT1,		/* irq number */
49 		.end	= IRQ_EXT1,
50 		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
51 	},
52 };
53 
54 static struct platform_device r8a66597_usb_host_device = {
55 	.name		= "r8a66597_hcd",
56 	.id		= -1,
57 	.dev = {
58 		.dma_mask		= NULL,		/* don't use dma */
59 		.coherent_dma_mask	= 0xffffffff,
60 		.platform_data		= &r8a66597_data,
61 	},
62 	.num_resources	= ARRAY_SIZE(r8a66597_usb_host_resources),
63 	.resource	= r8a66597_usb_host_resources,
64 };
65 
66 static struct m66592_platdata usbf_platdata = {
67 	.xtal = M66592_PLATDATA_XTAL_24MHZ,
68 	.vif = 1,
69 };
70 
71 static struct resource m66592_usb_peripheral_resources[] = {
72 	[0] = {
73 		.name	= "m66592_udc",
74 		.start	= 0xb0000000,
75 		.end	= 0xb00000FF,
76 		.flags	= IORESOURCE_MEM,
77 	},
78 	[1] = {
79 		.name	= "m66592_udc",
80 		.start	= IRQ_EXT4,		/* irq number */
81 		.end	= IRQ_EXT4,
82 		.flags	= IORESOURCE_IRQ,
83 	},
84 };
85 
86 static struct platform_device m66592_usb_peripheral_device = {
87 	.name		= "m66592_udc",
88 	.id		= -1,
89 	.dev = {
90 		.dma_mask		= NULL,		/* don't use dma */
91 		.coherent_dma_mask	= 0xffffffff,
92 		.platform_data		= &usbf_platdata,
93 	},
94 	.num_resources	= ARRAY_SIZE(m66592_usb_peripheral_resources),
95 	.resource	= m66592_usb_peripheral_resources,
96 };
97 
98 static struct resource cf_ide_resources[] = {
99 	[0] = {
100 		.start	= PA_AREA5_IO + 0x1000,
101 		.end	= PA_AREA5_IO + 0x1000 + 0x08 - 1,
102 		.flags	= IORESOURCE_MEM,
103 	},
104 	[1] = {
105 		.start	= PA_AREA5_IO + 0x80c,
106 		.end	= PA_AREA5_IO + 0x80c + 0x16 - 1,
107 		.flags	= IORESOURCE_MEM,
108 	},
109 	[2] = {
110 		.start	= IRQ_CF,
111 		.flags	= IORESOURCE_IRQ,
112 	},
113 };
114 
115 static struct pata_platform_info pata_info = {
116 	.ioport_shift	= 1,
117 };
118 
119 static struct platform_device cf_ide_device  = {
120 	.name		= "pata_platform",
121 	.id		= -1,
122 	.num_resources	= ARRAY_SIZE(cf_ide_resources),
123 	.resource	= cf_ide_resources,
124 	.dev	= {
125 		.platform_data	= &pata_info,
126 	},
127 };
128 
129 static struct resource heartbeat_resources[] = {
130 	[0] = {
131 		.start	= PA_OBLED,
132 		.end	= PA_OBLED,
133 		.flags	= IORESOURCE_MEM,
134 	},
135 };
136 
137 #ifndef CONFIG_SH_R7785RP
138 static unsigned char heartbeat_bit_pos[] = { 2, 1, 0, 3, 6, 5, 4, 7 };
139 
140 static struct heartbeat_data heartbeat_data = {
141 	.bit_pos	= heartbeat_bit_pos,
142 	.nr_bits	= ARRAY_SIZE(heartbeat_bit_pos),
143 };
144 #endif
145 
146 static struct platform_device heartbeat_device = {
147 	.name		= "heartbeat",
148 	.id		= -1,
149 
150 	/* R7785RP has a slightly more sensible FPGA.. */
151 #ifndef CONFIG_SH_R7785RP
152 	.dev	= {
153 		.platform_data	= &heartbeat_data,
154 	},
155 #endif
156 	.num_resources	= ARRAY_SIZE(heartbeat_resources),
157 	.resource	= heartbeat_resources,
158 };
159 
160 static struct ax_plat_data ax88796_platdata = {
161 	.flags          = AXFLG_HAS_93CX6,
162 	.wordlength     = 2,
163 	.dcr_val        = 0x1,
164 	.rcr_val        = 0x40,
165 };
166 
167 static struct resource ax88796_resources[] = {
168 	{
169 #ifdef CONFIG_SH_R7780RP
170 		.start  = 0xa5800400,
171 		.end    = 0xa5800400 + (0x20 * 0x2) - 1,
172 #else
173 		.start  = 0xa4100400,
174 		.end    = 0xa4100400 + (0x20 * 0x2) - 1,
175 #endif
176 		.flags  = IORESOURCE_MEM,
177 	},
178 	{
179 		.start  = IRQ_AX88796,
180 		.end    = IRQ_AX88796,
181 		.flags  = IORESOURCE_IRQ,
182 	},
183 };
184 
185 static struct platform_device ax88796_device = {
186 	.name           = "ax88796",
187 	.id             = 0,
188 
189 	.dev    = {
190 		.platform_data = &ax88796_platdata,
191 	},
192 
193 	.num_resources  = ARRAY_SIZE(ax88796_resources),
194 	.resource       = ax88796_resources,
195 };
196 
197 static struct mtd_partition nor_flash_partitions[] = {
198 	{
199 		.name		= "loader",
200 		.offset		= 0x00000000,
201 		.size		= 512 * 1024,
202 	},
203 	{
204 		.name		= "bootenv",
205 		.offset		= MTDPART_OFS_APPEND,
206 		.size		= 512 * 1024,
207 	},
208 	{
209 		.name		= "kernel",
210 		.offset		= MTDPART_OFS_APPEND,
211 		.size		= 4 * 1024 * 1024,
212 	},
213 	{
214 		.name		= "data",
215 		.offset		= MTDPART_OFS_APPEND,
216 		.size		= MTDPART_SIZ_FULL,
217 	},
218 };
219 
220 static struct physmap_flash_data nor_flash_data = {
221 	.width		= 4,
222 	.parts		= nor_flash_partitions,
223 	.nr_parts	= ARRAY_SIZE(nor_flash_partitions),
224 };
225 
226 /* This config is flash board for mass production. */
227 static struct resource nor_flash_resources[] = {
228 	[0]	= {
229 		.start	= PA_NORFLASH_ADDR,
230 		.end	= PA_NORFLASH_ADDR + PA_NORFLASH_SIZE - 1,
231 		.flags	= IORESOURCE_MEM,
232 	}
233 };
234 
235 static struct platform_device nor_flash_device = {
236 	.name		= "physmap-flash",
237 	.dev		= {
238 		.platform_data	= &nor_flash_data,
239 	},
240 	.num_resources	= ARRAY_SIZE(nor_flash_resources),
241 	.resource	= nor_flash_resources,
242 };
243 
244 static struct resource smbus_resources[] = {
245 	[0] = {
246 		.start	= PA_SMCR,
247 		.end	= PA_SMCR + 0x100 - 1,
248 		.flags	= IORESOURCE_MEM,
249 	},
250 	[1] = {
251 		.start	= IRQ_SMBUS,
252 		.end	= IRQ_SMBUS,
253 		.flags	= IORESOURCE_IRQ,
254 	},
255 };
256 
257 static struct platform_device smbus_device = {
258 	.name		= "i2c-highlander",
259 	.id		= 0,
260 	.num_resources	= ARRAY_SIZE(smbus_resources),
261 	.resource	= smbus_resources,
262 };
263 
264 static struct i2c_board_info __initdata highlander_i2c_devices[] = {
265 	{
266 		I2C_BOARD_INFO("r2025sd", 0x32),
267 	},
268 };
269 
270 static struct platform_device *r7780rp_devices[] __initdata = {
271 	&r8a66597_usb_host_device,
272 	&m66592_usb_peripheral_device,
273 	&heartbeat_device,
274 	&smbus_device,
275 	&nor_flash_device,
276 #ifndef CONFIG_SH_R7780RP
277 	&ax88796_device,
278 #endif
279 };
280 
281 /*
282  * The CF is connected using a 16-bit bus where 8-bit operations are
283  * unsupported. The linux ata driver is however using 8-bit operations, so
284  * insert a trapped io filter to convert 8-bit operations into 16-bit.
285  */
286 static struct trapped_io cf_trapped_io = {
287 	.resource		= cf_ide_resources,
288 	.num_resources		= 2,
289 	.minimum_bus_width	= 16,
290 };
291 
292 static int __init r7780rp_devices_setup(void)
293 {
294 	int ret = 0;
295 
296 #ifndef CONFIG_SH_R7780RP
297 	if (register_trapped_io(&cf_trapped_io) == 0)
298 		ret |= platform_device_register(&cf_ide_device);
299 #endif
300 
301 	ret |= platform_add_devices(r7780rp_devices,
302 				    ARRAY_SIZE(r7780rp_devices));
303 
304 	ret |= i2c_register_board_info(0, highlander_i2c_devices,
305 				       ARRAY_SIZE(highlander_i2c_devices));
306 
307 	return ret;
308 }
309 device_initcall(r7780rp_devices_setup);
310 
311 /*
312  * Platform specific clocks
313  */
314 static int ivdr_clk_enable(struct clk *clk)
315 {
316 	__raw_writew(__raw_readw(PA_IVDRCTL) | (1 << IVDR_CK_ON), PA_IVDRCTL);
317 	return 0;
318 }
319 
320 static void ivdr_clk_disable(struct clk *clk)
321 {
322 	__raw_writew(__raw_readw(PA_IVDRCTL) & ~(1 << IVDR_CK_ON), PA_IVDRCTL);
323 }
324 
325 static struct sh_clk_ops ivdr_clk_ops = {
326 	.enable		= ivdr_clk_enable,
327 	.disable	= ivdr_clk_disable,
328 };
329 
330 static struct clk ivdr_clk = {
331 	.ops		= &ivdr_clk_ops,
332 };
333 
334 static struct clk *r7780rp_clocks[] = {
335 	&ivdr_clk,
336 };
337 
338 static struct clk_lookup lookups[] = {
339 	/* main clocks */
340 	CLKDEV_CON_ID("ivdr_clk", &ivdr_clk),
341 };
342 
343 static void r7780rp_power_off(void)
344 {
345 	if (mach_is_r7780mp() || mach_is_r7785rp())
346 		__raw_writew(0x0001, PA_POFF);
347 }
348 
349 /*
350  * Initialize the board
351  */
352 static void __init highlander_setup(char **cmdline_p)
353 {
354 	u16 ver = __raw_readw(PA_VERREG);
355 	int i;
356 
357 	printk(KERN_INFO "Renesas Solutions Highlander %s support.\n",
358 			 mach_is_r7780rp() ? "R7780RP-1" :
359 			 mach_is_r7780mp() ? "R7780MP"	 :
360 					     "R7785RP");
361 
362 	printk(KERN_INFO "Board version: %d (revision %d), "
363 			 "FPGA version: %d (revision %d)\n",
364 			 (ver >> 12) & 0xf, (ver >> 8) & 0xf,
365 			 (ver >>  4) & 0xf, ver & 0xf);
366 
367 	highlander_plat_pinmux_setup();
368 
369 	/*
370 	 * Enable the important clocks right away..
371 	 */
372 	for (i = 0; i < ARRAY_SIZE(r7780rp_clocks); i++) {
373 		struct clk *clk = r7780rp_clocks[i];
374 
375 		clk_register(clk);
376 		clk_enable(clk);
377 	}
378 
379 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
380 
381 	__raw_writew(0x0000, PA_OBLED);	/* Clear LED. */
382 
383 	if (mach_is_r7780rp())
384 		__raw_writew(0x0001, PA_SDPOW);	/* SD Power ON */
385 
386 	__raw_writew(__raw_readw(PA_IVDRCTL) | 0x01, PA_IVDRCTL);	/* Si13112 */
387 
388 	pm_power_off = r7780rp_power_off;
389 }
390 
391 static unsigned char irl2irq[HL_NR_IRL];
392 
393 static int highlander_irq_demux(int irq)
394 {
395 	if (irq >= HL_NR_IRL || irq < 0 || !irl2irq[irq])
396 		return irq;
397 
398 	return irl2irq[irq];
399 }
400 
401 static void __init highlander_init_irq(void)
402 {
403 	unsigned char *ucp = highlander_plat_irq_setup();
404 
405 	if (ucp) {
406 		plat_irq_setup_pins(IRQ_MODE_IRL3210);
407 		memcpy(irl2irq, ucp, HL_NR_IRL);
408 	}
409 }
410 
411 /*
412  * The Machine Vector
413  */
414 static struct sh_machine_vector mv_highlander __initmv = {
415 	.mv_name		= "Highlander",
416 	.mv_setup		= highlander_setup,
417 	.mv_init_irq		= highlander_init_irq,
418 	.mv_irq_demux		= highlander_irq_demux,
419 };
420