diff options
| author | Afzal Mohammed <afzal@ti.com> | 2012-08-17 02:46:14 -0400 |
|---|---|---|
| committer | Afzal Mohammed <afzal@ti.com> | 2012-11-09 07:37:23 -0500 |
| commit | 47acde16726080e5157b602f23937d00a04cd2ed (patch) | |
| tree | 956d19bef0f4fa5b070fd093b9ddfbca30090c32 | |
| parent | ac2d9ae1947288677ec78cd91a29490234ab9854 (diff) | |
ARM: OMAP2+: tusb6010: generic timing calculation
Generic gpmc timing calculation helper is available now, use
it instead of custom timing calculation.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
| -rw-r--r-- | arch/arm/mach-omap2/usb-tusb6010.c | 182 |
1 files changed, 44 insertions, 138 deletions
diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c index 5be96c6e1416..c5a3c6f9504e 100644 --- a/arch/arm/mach-omap2/usb-tusb6010.c +++ b/arch/arm/mach-omap2/usb-tusb6010.c | |||
| @@ -27,182 +27,88 @@ static u8 async_cs, sync_cs; | |||
| 27 | static unsigned refclk_psec; | 27 | static unsigned refclk_psec; |
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | /* t2_ps, when quantized to fclk units, must happen no earlier than | ||
| 31 | * the clock after after t1_NS. | ||
| 32 | * | ||
| 33 | * Return a possibly updated value of t2_ps, converted to nsec. | ||
| 34 | */ | ||
| 35 | static unsigned | ||
| 36 | next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps) | ||
| 37 | { | ||
| 38 | unsigned t1_ps = t1_NS * 1000; | ||
| 39 | unsigned t1_f, t2_f; | ||
| 40 | |||
| 41 | if ((t1_ps + fclk_ps) < t2_ps) | ||
| 42 | return t2_ps / 1000; | ||
| 43 | |||
| 44 | t1_f = (t1_ps + fclk_ps - 1) / fclk_ps; | ||
| 45 | t2_f = (t2_ps + fclk_ps - 1) / fclk_ps; | ||
| 46 | |||
| 47 | if (t1_f >= t2_f) | ||
| 48 | t2_f = t1_f + 1; | ||
| 49 | |||
| 50 | return (t2_f * fclk_ps) / 1000; | ||
| 51 | } | ||
| 52 | |||
| 53 | /* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */ | 30 | /* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */ |
| 54 | 31 | ||
| 55 | static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps) | 32 | static int tusb_set_async_mode(unsigned sysclk_ps) |
| 56 | { | 33 | { |
| 34 | struct gpmc_device_timings dev_t; | ||
| 57 | struct gpmc_timings t; | 35 | struct gpmc_timings t; |
| 58 | unsigned t_acsnh_advnh = sysclk_ps + 3000; | 36 | unsigned t_acsnh_advnh = sysclk_ps + 3000; |
| 59 | unsigned tmp; | ||
| 60 | |||
| 61 | memset(&t, 0, sizeof(t)); | ||
| 62 | |||
| 63 | /* CS_ON = t_acsnh_acsnl */ | ||
| 64 | t.cs_on = 8; | ||
| 65 | /* ADV_ON = t_acsnh_advnh - t_advn */ | ||
| 66 | t.adv_on = next_clk(t.cs_on, t_acsnh_advnh - 7000, fclk_ps); | ||
| 67 | |||
| 68 | /* | ||
| 69 | * READ ... from omap2420 TRM fig 12-13 | ||
| 70 | */ | ||
| 71 | |||
| 72 | /* ADV_RD_OFF = t_acsnh_advnh */ | ||
| 73 | t.adv_rd_off = next_clk(t.adv_on, t_acsnh_advnh, fclk_ps); | ||
| 74 | |||
| 75 | /* OE_ON = t_acsnh_advnh + t_advn_oen (then wait for nRDY) */ | ||
| 76 | t.oe_on = next_clk(t.adv_on, t_acsnh_advnh + 1000, fclk_ps); | ||
| 77 | |||
| 78 | /* ACCESS = counters continue only after nRDY */ | ||
| 79 | tmp = t.oe_on * 1000 + 300; | ||
| 80 | t.access = next_clk(t.oe_on, tmp, fclk_ps); | ||
| 81 | |||
| 82 | /* OE_OFF = after data gets sampled */ | ||
| 83 | tmp = t.access * 1000; | ||
| 84 | t.oe_off = next_clk(t.access, tmp, fclk_ps); | ||
| 85 | |||
| 86 | t.cs_rd_off = t.oe_off; | ||
| 87 | |||
| 88 | tmp = t.cs_rd_off * 1000 + 7000 /* t_acsn_rdy_z */; | ||
| 89 | t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps); | ||
| 90 | |||
| 91 | /* | ||
| 92 | * WRITE ... from omap2420 TRM fig 12-15 | ||
| 93 | */ | ||
| 94 | 37 | ||
| 95 | /* ADV_WR_OFF = t_acsnh_advnh */ | 38 | memset(&dev_t, 0, sizeof(dev_t)); |
| 96 | t.adv_wr_off = t.adv_rd_off; | ||
| 97 | 39 | ||
| 98 | /* WE_ON = t_acsnh_advnh + t_advn_wen (then wait for nRDY) */ | 40 | dev_t.mux = true; |
| 99 | t.we_on = next_clk(t.adv_wr_off, t_acsnh_advnh + 1000, fclk_ps); | ||
| 100 | 41 | ||
| 101 | /* WE_OFF = after data gets sampled */ | 42 | dev_t.t_ceasu = 8 * 1000; |
| 102 | tmp = t.we_on * 1000 + 300; | 43 | dev_t.t_avdasu = t_acsnh_advnh - 7000; |
| 103 | t.we_off = next_clk(t.we_on, tmp, fclk_ps); | 44 | dev_t.t_ce_avd = 1000; |
| 45 | dev_t.t_avdp_r = t_acsnh_advnh; | ||
| 46 | dev_t.t_oeasu = t_acsnh_advnh + 1000; | ||
| 47 | dev_t.t_oe = 300; | ||
| 48 | dev_t.t_cez_r = 7000; | ||
| 49 | dev_t.t_cez_w = dev_t.t_cez_r; | ||
| 50 | dev_t.t_avdp_w = t_acsnh_advnh; | ||
| 51 | dev_t.t_weasu = t_acsnh_advnh + 1000; | ||
| 52 | dev_t.t_wpl = 300; | ||
| 53 | dev_t.cyc_aavdh_we = 1; | ||
| 104 | 54 | ||
| 105 | t.cs_wr_off = t.we_off; | 55 | gpmc_calc_timings(&t, &dev_t); |
| 106 | |||
| 107 | tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */; | ||
| 108 | t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps); | ||
| 109 | 56 | ||
| 110 | return gpmc_cs_set_timings(async_cs, &t); | 57 | return gpmc_cs_set_timings(async_cs, &t); |
| 111 | } | 58 | } |
| 112 | 59 | ||
| 113 | static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps) | 60 | static int tusb_set_sync_mode(unsigned sysclk_ps) |
| 114 | { | 61 | { |
| 62 | struct gpmc_device_timings dev_t; | ||
| 115 | struct gpmc_timings t; | 63 | struct gpmc_timings t; |
| 116 | unsigned t_scsnh_advnh = sysclk_ps + 3000; | 64 | unsigned t_scsnh_advnh = sysclk_ps + 3000; |
| 117 | unsigned tmp; | ||
| 118 | |||
| 119 | memset(&t, 0, sizeof(t)); | ||
| 120 | t.cs_on = 8; | ||
| 121 | |||
| 122 | /* ADV_ON = t_acsnh_advnh - t_advn */ | ||
| 123 | t.adv_on = next_clk(t.cs_on, t_scsnh_advnh - 7000, fclk_ps); | ||
| 124 | |||
| 125 | /* GPMC_CLK rate = fclk rate / div */ | ||
| 126 | t.sync_clk = 11100 /* 11.1 nsec */; | ||
| 127 | tmp = (t.sync_clk + fclk_ps - 1) / fclk_ps; | ||
| 128 | if (tmp > 4) | ||
| 129 | return -ERANGE; | ||
| 130 | if (tmp == 0) | ||
| 131 | tmp = 1; | ||
| 132 | t.page_burst_access = (fclk_ps * tmp) / 1000; | ||
| 133 | |||
| 134 | /* | ||
| 135 | * READ ... based on omap2420 TRM fig 12-19, 12-20 | ||
| 136 | */ | ||
| 137 | |||
| 138 | /* ADV_RD_OFF = t_scsnh_advnh */ | ||
| 139 | t.adv_rd_off = next_clk(t.adv_on, t_scsnh_advnh, fclk_ps); | ||
| 140 | |||
| 141 | /* OE_ON = t_scsnh_advnh + t_advn_oen * fclk_ps (then wait for nRDY) */ | ||
| 142 | tmp = (t.adv_rd_off * 1000) + (3 * fclk_ps); | ||
| 143 | t.oe_on = next_clk(t.adv_on, tmp, fclk_ps); | ||
| 144 | |||
| 145 | /* ACCESS = number of clock cycles after t_adv_eon */ | ||
| 146 | tmp = (t.oe_on * 1000) + (5 * fclk_ps); | ||
| 147 | t.access = next_clk(t.oe_on, tmp, fclk_ps); | ||
| 148 | |||
| 149 | /* OE_OFF = after data gets sampled */ | ||
| 150 | tmp = (t.access * 1000) + (1 * fclk_ps); | ||
| 151 | t.oe_off = next_clk(t.access, tmp, fclk_ps); | ||
| 152 | 65 | ||
| 153 | t.cs_rd_off = t.oe_off; | 66 | memset(&dev_t, 0, sizeof(dev_t)); |
| 154 | 67 | ||
| 155 | tmp = t.cs_rd_off * 1000 + 7000 /* t_scsn_rdy_z */; | 68 | dev_t.mux = true; |
| 156 | t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps); | 69 | dev_t.sync_read = true; |
| 157 | 70 | dev_t.sync_write = true; | |
| 158 | /* | 71 | |
| 159 | * WRITE ... based on omap2420 TRM fig 12-21 | 72 | dev_t.clk = 11100; |
| 160 | */ | 73 | dev_t.t_bacc = 1000; |
| 161 | 74 | dev_t.t_ces = 1000; | |
| 162 | /* ADV_WR_OFF = t_scsnh_advnh */ | 75 | dev_t.t_ceasu = 8 * 1000; |
| 163 | t.adv_wr_off = t.adv_rd_off; | 76 | dev_t.t_avdasu = t_scsnh_advnh - 7000; |
| 164 | 77 | dev_t.t_ce_avd = 1000; | |
| 165 | /* WE_ON = t_scsnh_advnh + t_advn_wen * fclk_ps (then wait for nRDY) */ | 78 | dev_t.t_avdp_r = t_scsnh_advnh; |
| 166 | tmp = (t.adv_wr_off * 1000) + (3 * fclk_ps); | 79 | dev_t.cyc_aavdh_oe = 3; |
| 167 | t.we_on = next_clk(t.adv_wr_off, tmp, fclk_ps); | 80 | dev_t.cyc_oe = 5; |
| 168 | 81 | dev_t.t_ce_rdyz = 7000; | |
| 169 | /* WE_OFF = number of clock cycles after t_adv_wen */ | 82 | dev_t.t_avdp_w = t_scsnh_advnh; |
| 170 | tmp = (t.we_on * 1000) + (6 * fclk_ps); | 83 | dev_t.cyc_aavdh_we = 3; |
| 171 | t.we_off = next_clk(t.we_on, tmp, fclk_ps); | 84 | dev_t.cyc_wpl = 6; |
| 172 | 85 | dev_t.t_ce_rdyz = 7000; | |
| 173 | t.cs_wr_off = t.we_off; | 86 | |
| 174 | 87 | gpmc_calc_timings(&t, &dev_t); | |
| 175 | tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */; | ||
| 176 | t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps); | ||
| 177 | |||
| 178 | t.clk_activation = gpmc_ticks_to_ns(1); | ||
| 179 | 88 | ||
| 180 | return gpmc_cs_set_timings(sync_cs, &t); | 89 | return gpmc_cs_set_timings(sync_cs, &t); |
| 181 | } | 90 | } |
| 182 | 91 | ||
| 183 | extern unsigned long gpmc_get_fclk_period(void); | ||
| 184 | |||
| 185 | /* tusb driver calls this when it changes the chip's clocking */ | 92 | /* tusb driver calls this when it changes the chip's clocking */ |
| 186 | int tusb6010_platform_retime(unsigned is_refclk) | 93 | int tusb6010_platform_retime(unsigned is_refclk) |
| 187 | { | 94 | { |
| 188 | static const char error[] = | 95 | static const char error[] = |
| 189 | KERN_ERR "tusb6010 %s retime error %d\n"; | 96 | KERN_ERR "tusb6010 %s retime error %d\n"; |
| 190 | 97 | ||
| 191 | unsigned fclk_ps = gpmc_get_fclk_period(); | ||
| 192 | unsigned sysclk_ps; | 98 | unsigned sysclk_ps; |
| 193 | int status; | 99 | int status; |
| 194 | 100 | ||
| 195 | if (!refclk_psec || fclk_ps == 0) | 101 | if (!refclk_psec) |
| 196 | return -ENODEV; | 102 | return -ENODEV; |
| 197 | 103 | ||
| 198 | sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60; | 104 | sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60; |
| 199 | 105 | ||
| 200 | status = tusb_set_async_mode(sysclk_ps, fclk_ps); | 106 | status = tusb_set_async_mode(sysclk_ps); |
| 201 | if (status < 0) { | 107 | if (status < 0) { |
| 202 | printk(error, "async", status); | 108 | printk(error, "async", status); |
| 203 | goto done; | 109 | goto done; |
| 204 | } | 110 | } |
| 205 | status = tusb_set_sync_mode(sysclk_ps, fclk_ps); | 111 | status = tusb_set_sync_mode(sysclk_ps); |
| 206 | if (status < 0) | 112 | if (status < 0) |
| 207 | printk(error, "sync", status); | 113 | printk(error, "sync", status); |
| 208 | done: | 114 | done: |
