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