xref: /linux/arch/arm/mach-omap2/usb-tusb6010.c (revision d524dac9279b6a41ffdf7ff7958c577f2e387db6)
1 /*
2  * linux/arch/arm/mach-omap2/usb-tusb6010.c
3  *
4  * Copyright (C) 2006 Nokia Corporation
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 
11 #include <linux/types.h>
12 #include <linux/errno.h>
13 #include <linux/delay.h>
14 #include <linux/platform_device.h>
15 #include <linux/gpio.h>
16 
17 #include <linux/usb/musb.h>
18 
19 #include <plat/gpmc.h>
20 
21 #include "mux.h"
22 
23 static u8		async_cs, sync_cs;
24 static unsigned		refclk_psec;
25 
26 
27 /* t2_ps, when quantized to fclk units, must happen no earlier than
28  * the clock after after t1_NS.
29  *
30  * Return a possibly updated value of t2_ps, converted to nsec.
31  */
32 static unsigned
33 next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps)
34 {
35 	unsigned	t1_ps = t1_NS * 1000;
36 	unsigned	t1_f, t2_f;
37 
38 	if ((t1_ps + fclk_ps) < t2_ps)
39 		return t2_ps / 1000;
40 
41 	t1_f = (t1_ps + fclk_ps - 1) / fclk_ps;
42 	t2_f = (t2_ps + fclk_ps - 1) / fclk_ps;
43 
44 	if (t1_f >= t2_f)
45 		t2_f = t1_f + 1;
46 
47 	return (t2_f * fclk_ps) / 1000;
48 }
49 
50 /* NOTE:  timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
51 
52 static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
53 {
54 	struct gpmc_timings	t;
55 	unsigned		t_acsnh_advnh = sysclk_ps + 3000;
56 	unsigned		tmp;
57 
58 	memset(&t, 0, sizeof(t));
59 
60 	/* CS_ON = t_acsnh_acsnl */
61 	t.cs_on = 8;
62 	/* ADV_ON = t_acsnh_advnh - t_advn */
63 	t.adv_on = next_clk(t.cs_on, t_acsnh_advnh - 7000, fclk_ps);
64 
65 	/*
66 	 * READ ... from omap2420 TRM fig 12-13
67 	 */
68 
69 	/* ADV_RD_OFF = t_acsnh_advnh */
70 	t.adv_rd_off = next_clk(t.adv_on, t_acsnh_advnh, fclk_ps);
71 
72 	/* OE_ON = t_acsnh_advnh + t_advn_oen (then wait for nRDY) */
73 	t.oe_on = next_clk(t.adv_on, t_acsnh_advnh + 1000, fclk_ps);
74 
75 	/* ACCESS = counters continue only after nRDY */
76 	tmp = t.oe_on * 1000 + 300;
77 	t.access = next_clk(t.oe_on, tmp, fclk_ps);
78 
79 	/* OE_OFF = after data gets sampled */
80 	tmp = t.access * 1000;
81 	t.oe_off = next_clk(t.access, tmp, fclk_ps);
82 
83 	t.cs_rd_off = t.oe_off;
84 
85 	tmp = t.cs_rd_off * 1000 + 7000 /* t_acsn_rdy_z */;
86 	t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps);
87 
88 	/*
89 	 * WRITE ... from omap2420 TRM fig 12-15
90 	 */
91 
92 	/* ADV_WR_OFF = t_acsnh_advnh */
93 	t.adv_wr_off = t.adv_rd_off;
94 
95 	/* WE_ON = t_acsnh_advnh + t_advn_wen (then wait for nRDY) */
96 	t.we_on = next_clk(t.adv_wr_off, t_acsnh_advnh + 1000, fclk_ps);
97 
98 	/* WE_OFF = after data gets sampled */
99 	tmp = t.we_on * 1000 + 300;
100 	t.we_off = next_clk(t.we_on, tmp, fclk_ps);
101 
102 	t.cs_wr_off = t.we_off;
103 
104 	tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */;
105 	t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
106 
107 	return gpmc_cs_set_timings(async_cs, &t);
108 }
109 
110 static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
111 {
112 	struct gpmc_timings	t;
113 	unsigned		t_scsnh_advnh = sysclk_ps + 3000;
114 	unsigned		tmp;
115 
116 	memset(&t, 0, sizeof(t));
117 	t.cs_on = 8;
118 
119 	/* ADV_ON = t_acsnh_advnh - t_advn */
120 	t.adv_on = next_clk(t.cs_on, t_scsnh_advnh - 7000, fclk_ps);
121 
122 	/* GPMC_CLK rate = fclk rate / div */
123 	t.sync_clk = 11100 /* 11.1 nsec */;
124 	tmp = (t.sync_clk + fclk_ps - 1) / fclk_ps;
125 	if (tmp > 4)
126 		return -ERANGE;
127 	if (tmp <= 0)
128 		tmp = 1;
129 	t.page_burst_access = (fclk_ps * tmp) / 1000;
130 
131 	/*
132 	 * READ ... based on omap2420 TRM fig 12-19, 12-20
133 	 */
134 
135 	/* ADV_RD_OFF = t_scsnh_advnh */
136 	t.adv_rd_off = next_clk(t.adv_on, t_scsnh_advnh, fclk_ps);
137 
138 	/* OE_ON = t_scsnh_advnh + t_advn_oen * fclk_ps (then wait for nRDY) */
139 	tmp = (t.adv_rd_off * 1000) + (3 * fclk_ps);
140 	t.oe_on = next_clk(t.adv_on, tmp, fclk_ps);
141 
142 	/* ACCESS = number of clock cycles after t_adv_eon */
143 	tmp = (t.oe_on * 1000) + (5 * fclk_ps);
144 	t.access = next_clk(t.oe_on, tmp, fclk_ps);
145 
146 	/* OE_OFF = after data gets sampled */
147 	tmp = (t.access * 1000) + (1 * fclk_ps);
148 	t.oe_off = next_clk(t.access, tmp, fclk_ps);
149 
150 	t.cs_rd_off = t.oe_off;
151 
152 	tmp = t.cs_rd_off * 1000 + 7000 /* t_scsn_rdy_z */;
153 	t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps);
154 
155 	/*
156 	 * WRITE ... based on omap2420 TRM fig 12-21
157 	 */
158 
159 	/* ADV_WR_OFF = t_scsnh_advnh */
160 	t.adv_wr_off = t.adv_rd_off;
161 
162 	/* WE_ON = t_scsnh_advnh + t_advn_wen * fclk_ps (then wait for nRDY) */
163 	tmp = (t.adv_wr_off * 1000) + (3 * fclk_ps);
164 	t.we_on = next_clk(t.adv_wr_off, tmp, fclk_ps);
165 
166 	/* WE_OFF = number of clock cycles after t_adv_wen */
167 	tmp = (t.we_on * 1000) + (6 * fclk_ps);
168 	t.we_off = next_clk(t.we_on, tmp, fclk_ps);
169 
170 	t.cs_wr_off = t.we_off;
171 
172 	tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */;
173 	t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
174 
175 	return gpmc_cs_set_timings(sync_cs, &t);
176 }
177 
178 extern unsigned long gpmc_get_fclk_period(void);
179 
180 /* tusb driver calls this when it changes the chip's clocking */
181 int tusb6010_platform_retime(unsigned is_refclk)
182 {
183 	static const char	error[] =
184 		KERN_ERR "tusb6010 %s retime error %d\n";
185 
186 	unsigned	fclk_ps = gpmc_get_fclk_period();
187 	unsigned	sysclk_ps;
188 	int		status;
189 
190 	if (!refclk_psec || fclk_ps == 0)
191 		return -ENODEV;
192 
193 	sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;
194 
195 	status = tusb_set_async_mode(sysclk_ps, fclk_ps);
196 	if (status < 0) {
197 		printk(error, "async", status);
198 		goto done;
199 	}
200 	status = tusb_set_sync_mode(sysclk_ps, fclk_ps);
201 	if (status < 0)
202 		printk(error, "sync", status);
203 done:
204 	return status;
205 }
206 EXPORT_SYMBOL_GPL(tusb6010_platform_retime);
207 
208 static struct resource tusb_resources[] = {
209 	/* Order is significant!  The start/end fields
210 	 * are updated during setup..
211 	 */
212 	{ /* Asynchronous access */
213 		.flags	= IORESOURCE_MEM,
214 	},
215 	{ /* Synchronous access */
216 		.flags	= IORESOURCE_MEM,
217 	},
218 	{ /* IRQ */
219 		.name	= "mc",
220 		.flags	= IORESOURCE_IRQ,
221 	},
222 };
223 
224 static u64 tusb_dmamask = ~(u32)0;
225 
226 static struct platform_device tusb_device = {
227 	.name		= "musb-tusb",
228 	.id		= -1,
229 	.dev = {
230 		.dma_mask		= &tusb_dmamask,
231 		.coherent_dma_mask	= 0xffffffff,
232 	},
233 	.num_resources	= ARRAY_SIZE(tusb_resources),
234 	.resource	= tusb_resources,
235 };
236 
237 
238 /* this may be called only from board-*.c setup code */
239 int __init
240 tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
241 		unsigned ps_refclk, unsigned waitpin,
242 		unsigned async, unsigned sync,
243 		unsigned irq, unsigned dmachan)
244 {
245 	int		status;
246 	static char	error[] __initdata =
247 		KERN_ERR "tusb6010 init error %d, %d\n";
248 
249 	/* ASYNC region, primarily for PIO */
250 	status = gpmc_cs_request(async, SZ_16M, (unsigned long *)
251 				&tusb_resources[0].start);
252 	if (status < 0) {
253 		printk(error, 1, status);
254 		return status;
255 	}
256 	tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
257 	async_cs = async;
258 	gpmc_cs_write_reg(async, GPMC_CS_CONFIG1,
259 			  GPMC_CONFIG1_PAGE_LEN(2)
260 			| GPMC_CONFIG1_WAIT_READ_MON
261 			| GPMC_CONFIG1_WAIT_WRITE_MON
262 			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
263 			| GPMC_CONFIG1_READTYPE_ASYNC
264 			| GPMC_CONFIG1_WRITETYPE_ASYNC
265 			| GPMC_CONFIG1_DEVICESIZE_16
266 			| GPMC_CONFIG1_DEVICETYPE_NOR
267 			| GPMC_CONFIG1_MUXADDDATA);
268 
269 
270 	/* SYNC region, primarily for DMA */
271 	status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
272 				&tusb_resources[1].start);
273 	if (status < 0) {
274 		printk(error, 2, status);
275 		return status;
276 	}
277 	tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
278 	sync_cs = sync;
279 	gpmc_cs_write_reg(sync, GPMC_CS_CONFIG1,
280 			  GPMC_CONFIG1_READMULTIPLE_SUPP
281 			| GPMC_CONFIG1_READTYPE_SYNC
282 			| GPMC_CONFIG1_WRITEMULTIPLE_SUPP
283 			| GPMC_CONFIG1_WRITETYPE_SYNC
284 			| GPMC_CONFIG1_CLKACTIVATIONTIME(1)
285 			| GPMC_CONFIG1_PAGE_LEN(2)
286 			| GPMC_CONFIG1_WAIT_READ_MON
287 			| GPMC_CONFIG1_WAIT_WRITE_MON
288 			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
289 			| GPMC_CONFIG1_DEVICESIZE_16
290 			| GPMC_CONFIG1_DEVICETYPE_NOR
291 			| GPMC_CONFIG1_MUXADDDATA
292 			/* fclk divider gets set later */
293 			);
294 
295 	/* IRQ */
296 	status = gpio_request(irq, "TUSB6010 irq");
297 	if (status < 0) {
298 		printk(error, 3, status);
299 		return status;
300 	}
301 	gpio_direction_input(irq);
302 	tusb_resources[2].start = irq + IH_GPIO_BASE;
303 
304 	/* set up memory timings ... can speed them up later */
305 	if (!ps_refclk) {
306 		printk(error, 4, status);
307 		return -ENODEV;
308 	}
309 	refclk_psec = ps_refclk;
310 	status = tusb6010_platform_retime(1);
311 	if (status < 0) {
312 		printk(error, 5, status);
313 		return status;
314 	}
315 
316 	/* finish device setup ... */
317 	if (!data) {
318 		printk(error, 6, status);
319 		return -ENODEV;
320 	}
321 	tusb_device.dev.platform_data = data;
322 
323 	/* REVISIT let the driver know what DMA channels work */
324 	if (!dmachan)
325 		tusb_device.dev.dma_mask = NULL;
326 	else {
327 		/* assume OMAP 2420 ES2.0 and later */
328 		if (dmachan & (1 << 0))
329 			omap_mux_init_signal("sys_ndmareq0", 0);
330 		if (dmachan & (1 << 1))
331 			omap_mux_init_signal("sys_ndmareq1", 0);
332 		if (dmachan & (1 << 2))
333 			omap_mux_init_signal("sys_ndmareq2", 0);
334 		if (dmachan & (1 << 3))
335 			omap_mux_init_signal("sys_ndmareq3", 0);
336 		if (dmachan & (1 << 4))
337 			omap_mux_init_signal("sys_ndmareq4", 0);
338 		if (dmachan & (1 << 5))
339 			omap_mux_init_signal("sys_ndmareq5", 0);
340 	}
341 
342 	/* so far so good ... register the device */
343 	status = platform_device_register(&tusb_device);
344 	if (status < 0) {
345 		printk(error, 7, status);
346 		return status;
347 	}
348 	return 0;
349 }
350