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 /arch/arm/mach-omap2 | |
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>
Diffstat (limited to 'arch/arm/mach-omap2')
-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: |