180 lines
4.3 KiB
ReStructuredText
180 lines
4.3 KiB
ReStructuredText
|
.. SPDX-License-Identifier: GPL-2.0
|
||
|
|
||
|
========================================
|
||
|
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: https://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).
|