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