mmci_qcom_dml.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. *
  3. * Copyright (c) 2011, The Linux Foundation. All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 and
  7. * only version 2 as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include <linux/of.h>
  16. #include <linux/of_dma.h>
  17. #include <linux/bitops.h>
  18. #include <linux/mmc/host.h>
  19. #include <linux/mmc/card.h>
  20. #include "mmci.h"
  21. /* Registers */
  22. #define DML_CONFIG 0x00
  23. #define PRODUCER_CRCI_MSK GENMASK(1, 0)
  24. #define PRODUCER_CRCI_DISABLE 0
  25. #define PRODUCER_CRCI_X_SEL BIT(0)
  26. #define PRODUCER_CRCI_Y_SEL BIT(1)
  27. #define CONSUMER_CRCI_MSK GENMASK(3, 2)
  28. #define CONSUMER_CRCI_DISABLE 0
  29. #define CONSUMER_CRCI_X_SEL BIT(2)
  30. #define CONSUMER_CRCI_Y_SEL BIT(3)
  31. #define PRODUCER_TRANS_END_EN BIT(4)
  32. #define BYPASS BIT(16)
  33. #define DIRECT_MODE BIT(17)
  34. #define INFINITE_CONS_TRANS BIT(18)
  35. #define DML_SW_RESET 0x08
  36. #define DML_PRODUCER_START 0x0c
  37. #define DML_CONSUMER_START 0x10
  38. #define DML_PRODUCER_PIPE_LOGICAL_SIZE 0x14
  39. #define DML_CONSUMER_PIPE_LOGICAL_SIZE 0x18
  40. #define DML_PIPE_ID 0x1c
  41. #define PRODUCER_PIPE_ID_SHFT 0
  42. #define PRODUCER_PIPE_ID_MSK GENMASK(4, 0)
  43. #define CONSUMER_PIPE_ID_SHFT 16
  44. #define CONSUMER_PIPE_ID_MSK GENMASK(20, 16)
  45. #define DML_PRODUCER_BAM_BLOCK_SIZE 0x24
  46. #define DML_PRODUCER_BAM_TRANS_SIZE 0x28
  47. /* other definitions */
  48. #define PRODUCER_PIPE_LOGICAL_SIZE 4096
  49. #define CONSUMER_PIPE_LOGICAL_SIZE 4096
  50. #define DML_OFFSET 0x800
  51. void dml_start_xfer(struct mmci_host *host, struct mmc_data *data)
  52. {
  53. u32 config;
  54. void __iomem *base = host->base + DML_OFFSET;
  55. if (data->flags & MMC_DATA_READ) {
  56. /* Read operation: configure DML for producer operation */
  57. /* Set producer CRCI-x and disable consumer CRCI */
  58. config = readl_relaxed(base + DML_CONFIG);
  59. config = (config & ~PRODUCER_CRCI_MSK) | PRODUCER_CRCI_X_SEL;
  60. config = (config & ~CONSUMER_CRCI_MSK) | CONSUMER_CRCI_DISABLE;
  61. writel_relaxed(config, base + DML_CONFIG);
  62. /* Set the Producer BAM block size */
  63. writel_relaxed(data->blksz, base + DML_PRODUCER_BAM_BLOCK_SIZE);
  64. /* Set Producer BAM Transaction size */
  65. writel_relaxed(data->blocks * data->blksz,
  66. base + DML_PRODUCER_BAM_TRANS_SIZE);
  67. /* Set Producer Transaction End bit */
  68. config = readl_relaxed(base + DML_CONFIG);
  69. config |= PRODUCER_TRANS_END_EN;
  70. writel_relaxed(config, base + DML_CONFIG);
  71. /* Trigger producer */
  72. writel_relaxed(1, base + DML_PRODUCER_START);
  73. } else {
  74. /* Write operation: configure DML for consumer operation */
  75. /* Set consumer CRCI-x and disable producer CRCI*/
  76. config = readl_relaxed(base + DML_CONFIG);
  77. config = (config & ~CONSUMER_CRCI_MSK) | CONSUMER_CRCI_X_SEL;
  78. config = (config & ~PRODUCER_CRCI_MSK) | PRODUCER_CRCI_DISABLE;
  79. writel_relaxed(config, base + DML_CONFIG);
  80. /* Clear Producer Transaction End bit */
  81. config = readl_relaxed(base + DML_CONFIG);
  82. config &= ~PRODUCER_TRANS_END_EN;
  83. writel_relaxed(config, base + DML_CONFIG);
  84. /* Trigger consumer */
  85. writel_relaxed(1, base + DML_CONSUMER_START);
  86. }
  87. /* make sure the dml is configured before dma is triggered */
  88. wmb();
  89. }
  90. static int of_get_dml_pipe_index(struct device_node *np, const char *name)
  91. {
  92. int index;
  93. struct of_phandle_args dma_spec;
  94. index = of_property_match_string(np, "dma-names", name);
  95. if (index < 0)
  96. return -ENODEV;
  97. if (of_parse_phandle_with_args(np, "dmas", "#dma-cells", index,
  98. &dma_spec))
  99. return -ENODEV;
  100. if (dma_spec.args_count)
  101. return dma_spec.args[0];
  102. return -ENODEV;
  103. }
  104. /* Initialize the dml hardware connected to SD Card controller */
  105. int dml_hw_init(struct mmci_host *host, struct device_node *np)
  106. {
  107. u32 config;
  108. void __iomem *base;
  109. int consumer_id, producer_id;
  110. consumer_id = of_get_dml_pipe_index(np, "tx");
  111. producer_id = of_get_dml_pipe_index(np, "rx");
  112. if (producer_id < 0 || consumer_id < 0)
  113. return -ENODEV;
  114. base = host->base + DML_OFFSET;
  115. /* Reset the DML block */
  116. writel_relaxed(1, base + DML_SW_RESET);
  117. /* Disable the producer and consumer CRCI */
  118. config = (PRODUCER_CRCI_DISABLE | CONSUMER_CRCI_DISABLE);
  119. /*
  120. * Disable the bypass mode. Bypass mode will only be used
  121. * if data transfer is to happen in PIO mode and don't
  122. * want the BAM interface to connect with SDCC-DML.
  123. */
  124. config &= ~BYPASS;
  125. /*
  126. * Disable direct mode as we don't DML to MASTER the AHB bus.
  127. * BAM connected with DML should MASTER the AHB bus.
  128. */
  129. config &= ~DIRECT_MODE;
  130. /*
  131. * Disable infinite mode transfer as we won't be doing any
  132. * infinite size data transfers. All data transfer will be
  133. * of finite data size.
  134. */
  135. config &= ~INFINITE_CONS_TRANS;
  136. writel_relaxed(config, base + DML_CONFIG);
  137. /*
  138. * Initialize the logical BAM pipe size for producer
  139. * and consumer.
  140. */
  141. writel_relaxed(PRODUCER_PIPE_LOGICAL_SIZE,
  142. base + DML_PRODUCER_PIPE_LOGICAL_SIZE);
  143. writel_relaxed(CONSUMER_PIPE_LOGICAL_SIZE,
  144. base + DML_CONSUMER_PIPE_LOGICAL_SIZE);
  145. /* Initialize Producer/consumer pipe id */
  146. writel_relaxed(producer_id | (consumer_id << CONSUMER_PIPE_ID_SHFT),
  147. base + DML_PIPE_ID);
  148. /* Make sure dml intialization is finished */
  149. mb();
  150. return 0;
  151. }