]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
dm: Add MMC subsystem analysis
authorMarek Vasut <marek.vasut@gmail.com>
Wed, 8 Aug 2012 01:42:20 +0000 (01:42 +0000)
committerWolfgang Denk <wd@denx.de>
Sun, 2 Sep 2012 16:00:00 +0000 (18:00 +0200)
Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
doc/driver-model/UDM-mmc.txt [new file with mode: 0644]

diff --git a/doc/driver-model/UDM-mmc.txt b/doc/driver-model/UDM-mmc.txt
new file mode 100644 (file)
index 0000000..bed4306
--- /dev/null
@@ -0,0 +1,319 @@
+The U-Boot Driver Model Project
+===============================
+MMC system analysis
+===================
+Marek Vasut <marek.vasut@gmail.com>
+2012-02-25
+
+I) Overview
+-----------
+
+The MMC subsystem is already quite dynamic in it's nature. It's only necessary
+to flip the subsystem to properly defined API.
+
+The probing process of MMC drivers start by calling "mmc_initialize()",
+implemented by MMC framework, from the architecture initialization file. The
+"mmc_initialize()" function in turn calls "board_mmc_init()" function and if
+this doesn't succeed, "cpu_mmc_init()" function is called. It is important to
+note that both of the "*_mmc_init()" functions have weak aliases to functions
+which automatically fail.
+
+Both of the "*_mmc_init()" functions though serve only one purpose. To call
+driver specific probe function, which in turn actually registers the driver with
+MMC subsystem. Each of the driver specific probe functions is currently done in
+very ad-hoc manner.
+
+The registration with the MMC subsystem is done by calling "mmc_register()",
+whose argument is a runtime configured structure of information about the MMC
+driver. Currently, the information structure is intermixed with driver's internal
+data. The description of the structure follows:
+
+struct mmc {
+ /*
+  * API: Allows this driver to be a member of the linked list of all MMC drivers
+  *      registered with MMC subsystem
+  */
+  struct list_head link;
+
+  /* DRIVER: Name of the registered driver */
+  char name[32];
+
+  /* DRIVER: Driver's private data */
+  void *priv;
+
+  /* DRIVER: Voltages the host bus can provide */
+  uint voltages;
+
+  /* API: Version of the card */
+  uint version;
+
+  /* API: Test if the driver was already initialized */
+  uint has_init;
+
+  /* DRIVER: Minimum frequency the host bus can provide */
+  uint f_min;
+
+  /* DRIVER: Maximum frequency the host bus can provide */
+  uint f_max;
+
+  /* API: Is the card SDHC */
+  int high_capacity;
+
+  /* API: Actual width of the bus used by the current card */
+  uint bus_width;
+
+  /*
+   * DRIVER: Clock frequency to be configured on the host bus, this is read-only
+   *         for the driver.
+   */
+  uint clock;
+
+  /* API: Capabilities of the card */
+  uint card_caps;
+
+  /* DRIVER: MMC bus capabilities */
+  uint host_caps;
+
+  /* API: Configuration and ID data retrieved from the card */
+  uint ocr;
+  uint scr[2];
+  uint csd[4];
+  uint cid[4];
+  ushort rca;
+
+  /* API: Partition configuration */
+  char part_config;
+
+  /* API: Number of partitions */
+  char part_num;
+
+  /* API: Transmission speed */
+  uint tran_speed;
+
+  /* API: Read block length */
+  uint read_bl_len;
+
+  /* API: Write block length */
+  uint write_bl_len;
+
+  /* API: Erase group size */
+  uint erase_grp_size;
+
+  /* API: Capacity of the card */
+  u64 capacity;
+
+  /* API: Descriptor of this block device */
+  block_dev_desc_t block_dev;
+
+  /* DRIVER: Function used to submit command to the card */
+  int (*send_cmd)(struct mmc *mmc,
+                  struct mmc_cmd *cmd, struct mmc_data *data);
+
+  /* DRIVER: Function used to configure the host */
+  void (*set_ios)(struct mmc *mmc);
+
+  /* DRIVER: Function used to initialize the host */
+  int (*init)(struct mmc *mmc);
+
+  /* DRIVER: Function used to report the status of Card Detect pin */
+  int (*getcd)(struct mmc *mmc);
+
+  /*
+   * DRIVER: Maximum amount of blocks sent during multiblock xfer,
+   *         set to 0 to autodetect.
+   */
+  uint b_max;
+};
+
+The API above is the new API used by most of the drivers. There're still drivers
+in the tree that use old, legacy API though.
+
+2) Approach
+-----------
+
+To convert the MMC subsystem to a proper driver model, the "struct mmc"
+structure will have to be properly split in the first place. The result will
+consist of multiple parts, first will be the structure defining operations
+provided by the MMC driver:
+
+struct mmc_driver_ops {
+  /* Function used to submit command to the card */
+  int  (*send_cmd)(struct mmc *mmc,
+                  struct mmc_cmd *cmd, struct mmc_data *data);
+  /* DRIVER: Function used to configure the host */
+  void (*set_ios)(struct mmc *mmc);
+  /* Function used to initialize the host */
+  int  (*init)(struct mmc *mmc);
+  /* Function used to report the status of Card Detect pin */
+  int  (*getcd)(struct mmc *mmc);
+}
+
+The second part will define the parameters of the MMC driver:
+
+struct mmc_driver_params {
+  /* Voltages the host bus can provide */
+  uint32_t voltages;
+  /* Minimum frequency the host bus can provide */
+  uint32_t f_min;
+  /* Maximum frequency the host bus can provide */
+  uint32_t f_max;
+  /* MMC bus capabilities */
+  uint32_t host_caps;
+  /*
+   * Maximum amount of blocks sent during multiblock xfer,
+   * set to 0 to autodetect.
+   */
+  uint32_t b_max;
+}
+
+And finally, the internal per-card data of the MMC subsystem core:
+
+struct mmc_card_props {
+  /* Version of the card */
+  uint32_t version;
+  /* Test if the driver was already initializes */
+  bool     has_init;
+  /* Is the card SDHC */
+  bool     high_capacity;
+  /* Actual width of the bus used by the current card */
+  uint8_t  bus_width;
+  /* Capabilities of the card */
+  uint32_t card_caps;
+  /* Configuration and ID data retrieved from the card */
+  uint32_t ocr;
+  uint32_t scr[2];
+  uint32_t csd[4];
+  uint32_t cid[4];
+  uint16_t rca;
+  /* Partition configuration */
+  uint8_t  part_config;
+  /* Number of partitions */
+  uint8_t  part_num;
+  /* Transmission speed */
+  uint32_t tran_speed;
+  /* Read block length */
+  uint32_t read_bl_len;
+  /* Write block length */
+  uint32_t write_bl_len;
+  /* Erase group size */
+  uint32_t erase_grp_size;
+  /* Capacity of the card */
+  uint64_t capacity;
+  /* Descriptor of this block device */
+  block_dev_desc_t block_dev;
+}
+
+The probe() function will then register the MMC driver by calling:
+
+  mmc_device_register(struct instance *i, struct mmc_driver_ops *o,
+                                          struct mmc_driver_params *p);
+
+The struct mmc_driver_params will have to be dynamic in some cases, but the
+driver shouldn't modify it's contents elsewhere than in probe() call.
+
+Next, since the MMC drivers will now be consistently registered into the driver
+tree from board file, the functions "board_mmc_init()" and "cpu_mmc_init()" will
+disappear altogether.
+
+As for the legacy drivers, these will either be converted or removed altogether.
+
+III) Analysis of in-tree drivers
+--------------------------------
+
+  1) arm_pl180_mmci.c
+  -------------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple.
+
+  2) atmel_mci.c
+  --------------
+  This driver uses the legacy API and should be removed unless converted. It is
+  probably possbible to replace this driver with gen_atmel_mci.c . No conversion
+  will be done on this driver.
+
+  3) bfin_sdh.c
+  -------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple.
+
+  4) davinci_mmc.c
+  ----------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple.
+
+  5) fsl_esdhc.c
+  --------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple, unless some problem appears due to the FDT
+  component of the driver.
+
+  6) ftsdc010_esdhc.c
+  -------------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple.
+
+  7) gen_atmel_mci.c
+  ------------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple.
+
+  8) mmc_spi.c
+  ------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple.
+
+  9) mv_sdhci.c
+  -------------
+  This is a component of the SDHCI support, allowing it to run on Marvell
+  Kirkwood chip. It is probable the SDHCI support will have to be modified to
+  allow calling functions from this file based on information passed via
+  platform_data.
+
+  10) mxcmmc.c
+  ------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple.
+
+  11) mxsmmc.c
+  ------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple.
+
+  12) omap_hsmmc.c
+  ----------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple.
+
+  13) pxa_mmc.c
+  -------------
+  This driver uses the legacy API and is written in a severely ad-hoc manner.
+  This driver will be removed in favor of pxa_mmc_gen.c, which is proved to work
+  better and is already well tested. No conversion will be done on this driver
+  anymore.
+
+  14) pxa_mmc_gen.c
+  -----------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple.
+
+  15) s5p_mmc.c
+  -------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple.
+
+  16) sdhci.c
+  -----------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple, though it'd be necessary to modify this driver
+  to also support the Kirkwood series and probably also Tegra series of CPUs.
+  See the respective parts of this section for details.
+
+  17) sh_mmcif.c
+  --------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple.
+
+  18) tegra2_mmc.c
+  ----------------
+  Follows the new API and also has a good encapsulation of the whole driver. The
+  conversion here will be simple.