// SPDX-License-Identifier: GPL-2.0-only /* * TI AEMIF driver * * Copyright (C) 2010 - 2013 Texas Instruments Incorporated. http://www.ti.com/ * * Authors: * Murali Karicheri <[email protected]> * Ivan Khoronzhuk <[email protected]> */ #include <linux/clk.h> #include <linux/err.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/platform_data/ti-aemif.h> #define TA_SHIFT … #define RHOLD_SHIFT … #define RSTROBE_SHIFT … #define RSETUP_SHIFT … #define WHOLD_SHIFT … #define WSTROBE_SHIFT … #define WSETUP_SHIFT … #define EW_SHIFT … #define SSTROBE_SHIFT … #define TA(x) … #define RHOLD(x) … #define RSTROBE(x) … #define RSETUP(x) … #define WHOLD(x) … #define WSTROBE(x) … #define WSETUP(x) … #define EW(x) … #define SSTROBE(x) … #define ASIZE_MAX … #define TA_MAX … #define RHOLD_MAX … #define RSTROBE_MAX … #define RSETUP_MAX … #define WHOLD_MAX … #define WSTROBE_MAX … #define WSETUP_MAX … #define EW_MAX … #define SSTROBE_MAX … #define NUM_CS … #define TA_VAL(x) … #define RHOLD_VAL(x) … #define RSTROBE_VAL(x) … #define RSETUP_VAL(x) … #define WHOLD_VAL(x) … #define WSTROBE_VAL(x) … #define WSETUP_VAL(x) … #define EW_VAL(x) … #define SSTROBE_VAL(x) … #define NRCSR_OFFSET … #define AWCCR_OFFSET … #define A1CR_OFFSET … #define ACR_ASIZE_MASK … #define ACR_EW_MASK … #define ACR_SSTROBE_MASK … #define ASIZE_16BIT … #define CONFIG_MASK … /** * struct aemif_cs_data: structure to hold cs parameters * @cs: chip-select number * @wstrobe: write strobe width, ns * @rstrobe: read strobe width, ns * @wsetup: write setup width, ns * @whold: write hold width, ns * @rsetup: read setup width, ns * @rhold: read hold width, ns * @ta: minimum turn around time, ns * @enable_ss: enable/disable select strobe mode * @enable_ew: enable/disable extended wait mode * @asize: width of the asynchronous device's data bus */ struct aemif_cs_data { … }; /** * struct aemif_device: structure to hold device data * @base: base address of AEMIF registers * @clk: source clock * @clk_rate: clock's rate in kHz * @num_cs: number of assigned chip-selects * @cs_offset: start number of cs nodes * @cs_data: array of chip-select settings */ struct aemif_device { … }; /** * aemif_calc_rate - calculate timing data. * @pdev: platform device to calculate for * @wanted: The cycle time needed in nanoseconds. * @clk: The input clock rate in kHz. * @max: The maximum divider value that can be programmed. * * On success, returns the calculated timing value minus 1 for easy * programming into AEMIF timing registers, else negative errno. */ static int aemif_calc_rate(struct platform_device *pdev, int wanted, unsigned long clk, int max) { … } /** * aemif_config_abus - configure async bus parameters * @pdev: platform device to configure for * @csnum: aemif chip select number * * This function programs the given timing values (in real clock) into the * AEMIF registers taking the AEMIF clock into account. * * This function does not use any locking while programming the AEMIF * because it is expected that there is only one user of a given * chip-select. * * Returns 0 on success, else negative errno. */ static int aemif_config_abus(struct platform_device *pdev, int csnum) { … } static inline int aemif_cycles_to_nsec(int val, unsigned long clk_rate) { … } /** * aemif_get_hw_params - function to read hw register values * @pdev: platform device to read for * @csnum: aemif chip select number * * This function reads the defaults from the registers and update * the timing values. Required for get/set commands and also for * the case when driver needs to use defaults in hardware. */ static void aemif_get_hw_params(struct platform_device *pdev, int csnum) { … } /** * of_aemif_parse_abus_config - parse CS configuration from DT * @pdev: platform device to parse for * @np: device node ptr * * This function update the emif async bus configuration based on the values * configured in a cs device binding node. */ static int of_aemif_parse_abus_config(struct platform_device *pdev, struct device_node *np) { … } static const struct of_device_id aemif_of_match[] = …; MODULE_DEVICE_TABLE(of, aemif_of_match); static int aemif_probe(struct platform_device *pdev) { … } static void aemif_remove(struct platform_device *pdev) { … } static struct platform_driver aemif_driver = …; module_platform_driver(…) …; MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; MODULE_ALIAS(…) …;