xref: /openbmc/linux/arch/arm/mach-omap2/usb-tusb6010.c (revision b8bb76713ec50df2f11efee386e16f93d51e1076)
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 <mach/gpmc.h>
20 #include <mach/mux.h>
21 
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 = 12 /* 11.1 nsec */;
124 	tmp = (t.sync_clk * 1000 + 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)
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 		.flags	= IORESOURCE_IRQ,
220 	},
221 };
222 
223 static u64 tusb_dmamask = ~(u32)0;
224 
225 static struct platform_device tusb_device = {
226 	.name		= "musb_hdrc",
227 	.id		= -1,
228 	.dev = {
229 		.dma_mask		= &tusb_dmamask,
230 		.coherent_dma_mask	= 0xffffffff,
231 	},
232 	.num_resources	= ARRAY_SIZE(tusb_resources),
233 	.resource	= tusb_resources,
234 };
235 
236 
237 /* this may be called only from board-*.c setup code */
238 int __init
239 tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
240 		unsigned ps_refclk, unsigned waitpin,
241 		unsigned async, unsigned sync,
242 		unsigned irq, unsigned dmachan)
243 {
244 	int		status;
245 	static char	error[] __initdata =
246 		KERN_ERR "tusb6010 init error %d, %d\n";
247 
248 	/* ASYNC region, primarily for PIO */
249 	status = gpmc_cs_request(async, SZ_16M, (unsigned long *)
250 				&tusb_resources[0].start);
251 	if (status < 0) {
252 		printk(error, 1, status);
253 		return status;
254 	}
255 	tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
256 	async_cs = async;
257 	gpmc_cs_write_reg(async, GPMC_CS_CONFIG1,
258 			  GPMC_CONFIG1_PAGE_LEN(2)
259 			| GPMC_CONFIG1_WAIT_READ_MON
260 			| GPMC_CONFIG1_WAIT_WRITE_MON
261 			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
262 			| GPMC_CONFIG1_READTYPE_ASYNC
263 			| GPMC_CONFIG1_WRITETYPE_ASYNC
264 			| GPMC_CONFIG1_DEVICESIZE_16
265 			| GPMC_CONFIG1_DEVICETYPE_NOR
266 			| GPMC_CONFIG1_MUXADDDATA);
267 
268 
269 	/* SYNC region, primarily for DMA */
270 	status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
271 				&tusb_resources[1].start);
272 	if (status < 0) {
273 		printk(error, 2, status);
274 		return status;
275 	}
276 	tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
277 	sync_cs = sync;
278 	gpmc_cs_write_reg(sync, GPMC_CS_CONFIG1,
279 			  GPMC_CONFIG1_READMULTIPLE_SUPP
280 			| GPMC_CONFIG1_READTYPE_SYNC
281 			| GPMC_CONFIG1_WRITEMULTIPLE_SUPP
282 			| GPMC_CONFIG1_WRITETYPE_SYNC
283 			| GPMC_CONFIG1_CLKACTIVATIONTIME(1)
284 			| GPMC_CONFIG1_PAGE_LEN(2)
285 			| GPMC_CONFIG1_WAIT_READ_MON
286 			| GPMC_CONFIG1_WAIT_WRITE_MON
287 			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
288 			| GPMC_CONFIG1_DEVICESIZE_16
289 			| GPMC_CONFIG1_DEVICETYPE_NOR
290 			| GPMC_CONFIG1_MUXADDDATA
291 			/* fclk divider gets set later */
292 			);
293 
294 	/* IRQ */
295 	status = gpio_request(irq, "TUSB6010 irq");
296 	if (status < 0) {
297 		printk(error, 3, status);
298 		return status;
299 	}
300 	gpio_direction_input(irq);
301 	tusb_resources[2].start = irq + IH_GPIO_BASE;
302 
303 	/* set up memory timings ... can speed them up later */
304 	if (!ps_refclk) {
305 		printk(error, 4, status);
306 		return -ENODEV;
307 	}
308 	refclk_psec = ps_refclk;
309 	status = tusb6010_platform_retime(1);
310 	if (status < 0) {
311 		printk(error, 5, status);
312 		return status;
313 	}
314 
315 	/* finish device setup ... */
316 	if (!data) {
317 		printk(error, 6, status);
318 		return -ENODEV;
319 	}
320 	tusb_device.dev.platform_data = data;
321 
322 	/* REVISIT let the driver know what DMA channels work */
323 	if (!dmachan)
324 		tusb_device.dev.dma_mask = NULL;
325 	else {
326 		/* assume OMAP 2420 ES2.0 and later */
327 		if (dmachan & (1 << 0))
328 			omap_cfg_reg(AA10_242X_DMAREQ0);
329 		if (dmachan & (1 << 1))
330 			omap_cfg_reg(AA6_242X_DMAREQ1);
331 		if (dmachan & (1 << 2))
332 			omap_cfg_reg(E4_242X_DMAREQ2);
333 		if (dmachan & (1 << 3))
334 			omap_cfg_reg(G4_242X_DMAREQ3);
335 		if (dmachan & (1 << 4))
336 			omap_cfg_reg(D3_242X_DMAREQ4);
337 		if (dmachan & (1 << 5))
338 			omap_cfg_reg(E3_242X_DMAREQ5);
339 	}
340 
341 	/* so far so good ... register the device */
342 	status = platform_device_register(&tusb_device);
343 	if (status < 0) {
344 		printk(error, 7, status);
345 		return status;
346 	}
347 	return 0;
348 }
349