123 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
GPMC (General Purpose Memory Controller):
 | 
						|
=========================================
 | 
						|
 | 
						|
GPMC is an unified memory controller dedicated to interfacing external
 | 
						|
memory devices like
 | 
						|
 * Asynchronous SRAM like memories and application specific integrated
 | 
						|
   circuit devices.
 | 
						|
 * Asynchronous, synchronous, and page mode burst NOR flash devices
 | 
						|
   NAND flash
 | 
						|
 * Pseudo-SRAM devices
 | 
						|
 | 
						|
GPMC is found on Texas Instruments SoC's (OMAP based)
 | 
						|
IP details: http://www.ti.com/lit/pdf/spruh73 section 7.1
 | 
						|
 | 
						|
 | 
						|
GPMC generic timing calculation:
 | 
						|
================================
 | 
						|
 | 
						|
GPMC has certain timings that has to be programmed for proper
 | 
						|
functioning of the peripheral, while peripheral has another set of
 | 
						|
timings. To have peripheral work with gpmc, peripheral timings has to
 | 
						|
be translated to the form gpmc can understand. The way it has to be
 | 
						|
translated depends on the connected peripheral. Also there is a
 | 
						|
dependency for certain gpmc timings on gpmc clock frequency. Hence a
 | 
						|
generic timing routine was developed to achieve above requirements.
 | 
						|
 | 
						|
Generic routine provides a generic method to calculate gpmc timings
 | 
						|
from gpmc peripheral timings. struct gpmc_device_timings fields has to
 | 
						|
be updated with timings from the datasheet of the peripheral that is
 | 
						|
connected to gpmc. A few of the peripheral timings can be fed either
 | 
						|
in time or in cycles, provision to handle this scenario has been
 | 
						|
provided (refer struct gpmc_device_timings definition). It may so
 | 
						|
happen that timing as specified by peripheral datasheet is not present
 | 
						|
in timing structure, in this scenario, try to correlate peripheral
 | 
						|
timing to the one available. If that doesn't work, try to add a new
 | 
						|
field as required by peripheral, educate generic timing routine to
 | 
						|
handle it, make sure that it does not break any of the existing.
 | 
						|
Then there may be cases where peripheral datasheet doesn't mention
 | 
						|
certain fields of struct gpmc_device_timings, zero those entries.
 | 
						|
 | 
						|
Generic timing routine has been verified to work properly on
 | 
						|
multiple onenand's and tusb6010 peripherals.
 | 
						|
 | 
						|
A word of caution: generic timing routine has been developed based
 | 
						|
on understanding of gpmc timings, peripheral timings, available
 | 
						|
custom timing routines, a kind of reverse engineering without
 | 
						|
most of the datasheets & hardware (to be exact none of those supported
 | 
						|
in mainline having custom timing routine) and by simulation.
 | 
						|
 | 
						|
gpmc timing dependency on peripheral timings:
 | 
						|
[<gpmc_timing>: <peripheral timing1>, <peripheral timing2> ...]
 | 
						|
 | 
						|
1. common
 | 
						|
cs_on: t_ceasu
 | 
						|
adv_on: t_avdasu, t_ceavd
 | 
						|
 | 
						|
2. sync common
 | 
						|
sync_clk: clk
 | 
						|
page_burst_access: t_bacc
 | 
						|
clk_activation: t_ces, t_avds
 | 
						|
 | 
						|
3. read async muxed
 | 
						|
adv_rd_off: t_avdp_r
 | 
						|
oe_on: t_oeasu, t_aavdh
 | 
						|
access: t_iaa, t_oe, t_ce, t_aa
 | 
						|
rd_cycle: t_rd_cycle, t_cez_r, t_oez
 | 
						|
 | 
						|
4. read async non-muxed
 | 
						|
adv_rd_off: t_avdp_r
 | 
						|
oe_on: t_oeasu
 | 
						|
access: t_iaa, t_oe, t_ce, t_aa
 | 
						|
rd_cycle: t_rd_cycle, t_cez_r, t_oez
 | 
						|
 | 
						|
5. read sync muxed
 | 
						|
adv_rd_off: t_avdp_r, t_avdh
 | 
						|
oe_on: t_oeasu, t_ach, cyc_aavdh_oe
 | 
						|
access: t_iaa, cyc_iaa, cyc_oe
 | 
						|
rd_cycle: t_cez_r, t_oez, t_ce_rdyz
 | 
						|
 | 
						|
6. read sync non-muxed
 | 
						|
adv_rd_off: t_avdp_r
 | 
						|
oe_on: t_oeasu
 | 
						|
access: t_iaa, cyc_iaa, cyc_oe
 | 
						|
rd_cycle: t_cez_r, t_oez, t_ce_rdyz
 | 
						|
 | 
						|
7. write async muxed
 | 
						|
adv_wr_off: t_avdp_w
 | 
						|
we_on, wr_data_mux_bus: t_weasu, t_aavdh, cyc_aavhd_we
 | 
						|
we_off: t_wpl
 | 
						|
cs_wr_off: t_wph
 | 
						|
wr_cycle: t_cez_w, t_wr_cycle
 | 
						|
 | 
						|
8. write async non-muxed
 | 
						|
adv_wr_off: t_avdp_w
 | 
						|
we_on, wr_data_mux_bus: t_weasu
 | 
						|
we_off: t_wpl
 | 
						|
cs_wr_off: t_wph
 | 
						|
wr_cycle: t_cez_w, t_wr_cycle
 | 
						|
 | 
						|
9. write sync muxed
 | 
						|
adv_wr_off: t_avdp_w, t_avdh
 | 
						|
we_on, wr_data_mux_bus: t_weasu, t_rdyo, t_aavdh, cyc_aavhd_we
 | 
						|
we_off: t_wpl, cyc_wpl
 | 
						|
cs_wr_off: t_wph
 | 
						|
wr_cycle: t_cez_w, t_ce_rdyz
 | 
						|
 | 
						|
10. write sync non-muxed
 | 
						|
adv_wr_off: t_avdp_w
 | 
						|
we_on, wr_data_mux_bus: t_weasu, t_rdyo
 | 
						|
we_off: t_wpl, cyc_wpl
 | 
						|
cs_wr_off: t_wph
 | 
						|
wr_cycle: t_cez_w, t_ce_rdyz
 | 
						|
 | 
						|
 | 
						|
Note: Many of gpmc timings are dependent on other gpmc timings (a few
 | 
						|
gpmc timings purely dependent on other gpmc timings, a reason that
 | 
						|
some of the gpmc timings are missing above), and it will result in
 | 
						|
indirect dependency of peripheral timings to gpmc timings other than
 | 
						|
mentioned above, refer timing routine for more details. To know what
 | 
						|
these peripheral timings correspond to, please see explanations in
 | 
						|
struct gpmc_device_timings definition. And for gpmc timings refer
 | 
						|
IP details (link above).
 |