arm: fix implicit use of sched.h in bcmring/dma.c
[linux-2.6/libata-dev.git] / arch / arm / mach-omap2 / usb-tusb6010.c
blob11760d2e29075d7b0860640a3f038983704f3b7e
1 /*
2 * linux/arch/arm/mach-omap2/usb-tusb6010.c
4 * Copyright (C) 2006 Nokia Corporation
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 */
11 #include <linux/string.h>
12 #include <linux/types.h>
13 #include <linux/errno.h>
14 #include <linux/delay.h>
15 #include <linux/platform_device.h>
16 #include <linux/gpio.h>
18 #include <linux/usb/musb.h>
20 #include <plat/gpmc.h>
22 #include "mux.h"
24 static u8 async_cs, sync_cs;
25 static unsigned refclk_psec;
28 /* t2_ps, when quantized to fclk units, must happen no earlier than
29 * the clock after after t1_NS.
31 * Return a possibly updated value of t2_ps, converted to nsec.
33 static unsigned
34 next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps)
36 unsigned t1_ps = t1_NS * 1000;
37 unsigned t1_f, t2_f;
39 if ((t1_ps + fclk_ps) < t2_ps)
40 return t2_ps / 1000;
42 t1_f = (t1_ps + fclk_ps - 1) / fclk_ps;
43 t2_f = (t2_ps + fclk_ps - 1) / fclk_ps;
45 if (t1_f >= t2_f)
46 t2_f = t1_f + 1;
48 return (t2_f * fclk_ps) / 1000;
51 /* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
53 static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
55 struct gpmc_timings t;
56 unsigned t_acsnh_advnh = sysclk_ps + 3000;
57 unsigned tmp;
59 memset(&t, 0, sizeof(t));
61 /* CS_ON = t_acsnh_acsnl */
62 t.cs_on = 8;
63 /* ADV_ON = t_acsnh_advnh - t_advn */
64 t.adv_on = next_clk(t.cs_on, t_acsnh_advnh - 7000, fclk_ps);
67 * READ ... from omap2420 TRM fig 12-13
70 /* ADV_RD_OFF = t_acsnh_advnh */
71 t.adv_rd_off = next_clk(t.adv_on, t_acsnh_advnh, fclk_ps);
73 /* OE_ON = t_acsnh_advnh + t_advn_oen (then wait for nRDY) */
74 t.oe_on = next_clk(t.adv_on, t_acsnh_advnh + 1000, fclk_ps);
76 /* ACCESS = counters continue only after nRDY */
77 tmp = t.oe_on * 1000 + 300;
78 t.access = next_clk(t.oe_on, tmp, fclk_ps);
80 /* OE_OFF = after data gets sampled */
81 tmp = t.access * 1000;
82 t.oe_off = next_clk(t.access, tmp, fclk_ps);
84 t.cs_rd_off = t.oe_off;
86 tmp = t.cs_rd_off * 1000 + 7000 /* t_acsn_rdy_z */;
87 t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps);
90 * WRITE ... from omap2420 TRM fig 12-15
93 /* ADV_WR_OFF = t_acsnh_advnh */
94 t.adv_wr_off = t.adv_rd_off;
96 /* WE_ON = t_acsnh_advnh + t_advn_wen (then wait for nRDY) */
97 t.we_on = next_clk(t.adv_wr_off, t_acsnh_advnh + 1000, fclk_ps);
99 /* WE_OFF = after data gets sampled */
100 tmp = t.we_on * 1000 + 300;
101 t.we_off = next_clk(t.we_on, tmp, fclk_ps);
103 t.cs_wr_off = t.we_off;
105 tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */;
106 t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
108 return gpmc_cs_set_timings(async_cs, &t);
111 static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
113 struct gpmc_timings t;
114 unsigned t_scsnh_advnh = sysclk_ps + 3000;
115 unsigned tmp;
117 memset(&t, 0, sizeof(t));
118 t.cs_on = 8;
120 /* ADV_ON = t_acsnh_advnh - t_advn */
121 t.adv_on = next_clk(t.cs_on, t_scsnh_advnh - 7000, fclk_ps);
123 /* GPMC_CLK rate = fclk rate / div */
124 t.sync_clk = 11100 /* 11.1 nsec */;
125 tmp = (t.sync_clk + fclk_ps - 1) / fclk_ps;
126 if (tmp > 4)
127 return -ERANGE;
128 if (tmp <= 0)
129 tmp = 1;
130 t.page_burst_access = (fclk_ps * tmp) / 1000;
133 * READ ... based on omap2420 TRM fig 12-19, 12-20
136 /* ADV_RD_OFF = t_scsnh_advnh */
137 t.adv_rd_off = next_clk(t.adv_on, t_scsnh_advnh, fclk_ps);
139 /* OE_ON = t_scsnh_advnh + t_advn_oen * fclk_ps (then wait for nRDY) */
140 tmp = (t.adv_rd_off * 1000) + (3 * fclk_ps);
141 t.oe_on = next_clk(t.adv_on, tmp, fclk_ps);
143 /* ACCESS = number of clock cycles after t_adv_eon */
144 tmp = (t.oe_on * 1000) + (5 * fclk_ps);
145 t.access = next_clk(t.oe_on, tmp, fclk_ps);
147 /* OE_OFF = after data gets sampled */
148 tmp = (t.access * 1000) + (1 * fclk_ps);
149 t.oe_off = next_clk(t.access, tmp, fclk_ps);
151 t.cs_rd_off = t.oe_off;
153 tmp = t.cs_rd_off * 1000 + 7000 /* t_scsn_rdy_z */;
154 t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps);
157 * WRITE ... based on omap2420 TRM fig 12-21
160 /* ADV_WR_OFF = t_scsnh_advnh */
161 t.adv_wr_off = t.adv_rd_off;
163 /* WE_ON = t_scsnh_advnh + t_advn_wen * fclk_ps (then wait for nRDY) */
164 tmp = (t.adv_wr_off * 1000) + (3 * fclk_ps);
165 t.we_on = next_clk(t.adv_wr_off, tmp, fclk_ps);
167 /* WE_OFF = number of clock cycles after t_adv_wen */
168 tmp = (t.we_on * 1000) + (6 * fclk_ps);
169 t.we_off = next_clk(t.we_on, tmp, fclk_ps);
171 t.cs_wr_off = t.we_off;
173 tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */;
174 t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
176 return gpmc_cs_set_timings(sync_cs, &t);
179 extern unsigned long gpmc_get_fclk_period(void);
181 /* tusb driver calls this when it changes the chip's clocking */
182 int tusb6010_platform_retime(unsigned is_refclk)
184 static const char error[] =
185 KERN_ERR "tusb6010 %s retime error %d\n";
187 unsigned fclk_ps = gpmc_get_fclk_period();
188 unsigned sysclk_ps;
189 int status;
191 if (!refclk_psec || fclk_ps == 0)
192 return -ENODEV;
194 sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;
196 status = tusb_set_async_mode(sysclk_ps, fclk_ps);
197 if (status < 0) {
198 printk(error, "async", status);
199 goto done;
201 status = tusb_set_sync_mode(sysclk_ps, fclk_ps);
202 if (status < 0)
203 printk(error, "sync", status);
204 done:
205 return status;
207 EXPORT_SYMBOL_GPL(tusb6010_platform_retime);
209 static struct resource tusb_resources[] = {
210 /* Order is significant! The start/end fields
211 * are updated during setup..
213 { /* Asynchronous access */
214 .flags = IORESOURCE_MEM,
216 { /* Synchronous access */
217 .flags = IORESOURCE_MEM,
219 { /* IRQ */
220 .name = "mc",
221 .flags = IORESOURCE_IRQ,
225 static u64 tusb_dmamask = ~(u32)0;
227 static struct platform_device tusb_device = {
228 .name = "musb-tusb",
229 .id = -1,
230 .dev = {
231 .dma_mask = &tusb_dmamask,
232 .coherent_dma_mask = 0xffffffff,
234 .num_resources = ARRAY_SIZE(tusb_resources),
235 .resource = tusb_resources,
239 /* this may be called only from board-*.c setup code */
240 int __init
241 tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
242 unsigned ps_refclk, unsigned waitpin,
243 unsigned async, unsigned sync,
244 unsigned irq, unsigned dmachan)
246 int status;
247 static char error[] __initdata =
248 KERN_ERR "tusb6010 init error %d, %d\n";
250 /* ASYNC region, primarily for PIO */
251 status = gpmc_cs_request(async, SZ_16M, (unsigned long *)
252 &tusb_resources[0].start);
253 if (status < 0) {
254 printk(error, 1, status);
255 return status;
257 tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
258 async_cs = async;
259 gpmc_cs_write_reg(async, GPMC_CS_CONFIG1,
260 GPMC_CONFIG1_PAGE_LEN(2)
261 | GPMC_CONFIG1_WAIT_READ_MON
262 | GPMC_CONFIG1_WAIT_WRITE_MON
263 | GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
264 | GPMC_CONFIG1_READTYPE_ASYNC
265 | GPMC_CONFIG1_WRITETYPE_ASYNC
266 | GPMC_CONFIG1_DEVICESIZE_16
267 | GPMC_CONFIG1_DEVICETYPE_NOR
268 | GPMC_CONFIG1_MUXADDDATA);
271 /* SYNC region, primarily for DMA */
272 status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
273 &tusb_resources[1].start);
274 if (status < 0) {
275 printk(error, 2, status);
276 return status;
278 tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
279 sync_cs = sync;
280 gpmc_cs_write_reg(sync, GPMC_CS_CONFIG1,
281 GPMC_CONFIG1_READMULTIPLE_SUPP
282 | GPMC_CONFIG1_READTYPE_SYNC
283 | GPMC_CONFIG1_WRITEMULTIPLE_SUPP
284 | GPMC_CONFIG1_WRITETYPE_SYNC
285 | GPMC_CONFIG1_CLKACTIVATIONTIME(1)
286 | GPMC_CONFIG1_PAGE_LEN(2)
287 | GPMC_CONFIG1_WAIT_READ_MON
288 | GPMC_CONFIG1_WAIT_WRITE_MON
289 | GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
290 | GPMC_CONFIG1_DEVICESIZE_16
291 | GPMC_CONFIG1_DEVICETYPE_NOR
292 | GPMC_CONFIG1_MUXADDDATA
293 /* fclk divider gets set later */
296 /* IRQ */
297 status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq");
298 if (status < 0) {
299 printk(error, 3, status);
300 return status;
302 tusb_resources[2].start = irq + IH_GPIO_BASE;
304 /* set up memory timings ... can speed them up later */
305 if (!ps_refclk) {
306 printk(error, 4, status);
307 return -ENODEV;
309 refclk_psec = ps_refclk;
310 status = tusb6010_platform_retime(1);
311 if (status < 0) {
312 printk(error, 5, status);
313 return status;
316 /* finish device setup ... */
317 if (!data) {
318 printk(error, 6, status);
319 return -ENODEV;
321 tusb_device.dev.platform_data = data;
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);
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;
348 return 0;