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).
|