3 * Copyright (c) 2011, The Linux Foundation. All rights reserved.
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.
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.
16 #include <linux/of_dma.h>
17 #include <linux/bitops.h>
18 #include <linux/mmc/host.h>
19 #include <linux/mmc/card.h>
23 #define DML_CONFIG 0x00
24 #define PRODUCER_CRCI_MSK GENMASK(1, 0)
25 #define PRODUCER_CRCI_DISABLE 0
26 #define PRODUCER_CRCI_X_SEL BIT(0)
27 #define PRODUCER_CRCI_Y_SEL BIT(1)
28 #define CONSUMER_CRCI_MSK GENMASK(3, 2)
29 #define CONSUMER_CRCI_DISABLE 0
30 #define CONSUMER_CRCI_X_SEL BIT(2)
31 #define CONSUMER_CRCI_Y_SEL BIT(3)
32 #define PRODUCER_TRANS_END_EN BIT(4)
33 #define BYPASS BIT(16)
34 #define DIRECT_MODE BIT(17)
35 #define INFINITE_CONS_TRANS BIT(18)
37 #define DML_SW_RESET 0x08
38 #define DML_PRODUCER_START 0x0c
39 #define DML_CONSUMER_START 0x10
40 #define DML_PRODUCER_PIPE_LOGICAL_SIZE 0x14
41 #define DML_CONSUMER_PIPE_LOGICAL_SIZE 0x18
42 #define DML_PIPE_ID 0x1c
43 #define PRODUCER_PIPE_ID_SHFT 0
44 #define PRODUCER_PIPE_ID_MSK GENMASK(4, 0)
45 #define CONSUMER_PIPE_ID_SHFT 16
46 #define CONSUMER_PIPE_ID_MSK GENMASK(20, 16)
48 #define DML_PRODUCER_BAM_BLOCK_SIZE 0x24
49 #define DML_PRODUCER_BAM_TRANS_SIZE 0x28
51 /* other definitions */
52 #define PRODUCER_PIPE_LOGICAL_SIZE 4096
53 #define CONSUMER_PIPE_LOGICAL_SIZE 4096
55 #define DML_OFFSET 0x800
57 static int qcom_dma_start(struct mmci_host *host, unsigned int *datactrl)
60 void __iomem *base = host->base + DML_OFFSET;
61 struct mmc_data *data = host->data;
62 int ret = mmci_dmae_start(host, datactrl);
67 if (data->flags & MMC_DATA_READ) {
68 /* Read operation: configure DML for producer operation */
69 /* Set producer CRCI-x and disable consumer CRCI */
70 config = readl_relaxed(base + DML_CONFIG);
71 config = (config & ~PRODUCER_CRCI_MSK) | PRODUCER_CRCI_X_SEL;
72 config = (config & ~CONSUMER_CRCI_MSK) | CONSUMER_CRCI_DISABLE;
73 writel_relaxed(config, base + DML_CONFIG);
75 /* Set the Producer BAM block size */
76 writel_relaxed(data->blksz, base + DML_PRODUCER_BAM_BLOCK_SIZE);
78 /* Set Producer BAM Transaction size */
79 writel_relaxed(data->blocks * data->blksz,
80 base + DML_PRODUCER_BAM_TRANS_SIZE);
81 /* Set Producer Transaction End bit */
82 config = readl_relaxed(base + DML_CONFIG);
83 config |= PRODUCER_TRANS_END_EN;
84 writel_relaxed(config, base + DML_CONFIG);
85 /* Trigger producer */
86 writel_relaxed(1, base + DML_PRODUCER_START);
88 /* Write operation: configure DML for consumer operation */
89 /* Set consumer CRCI-x and disable producer CRCI*/
90 config = readl_relaxed(base + DML_CONFIG);
91 config = (config & ~CONSUMER_CRCI_MSK) | CONSUMER_CRCI_X_SEL;
92 config = (config & ~PRODUCER_CRCI_MSK) | PRODUCER_CRCI_DISABLE;
93 writel_relaxed(config, base + DML_CONFIG);
94 /* Clear Producer Transaction End bit */
95 config = readl_relaxed(base + DML_CONFIG);
96 config &= ~PRODUCER_TRANS_END_EN;
97 writel_relaxed(config, base + DML_CONFIG);
98 /* Trigger consumer */
99 writel_relaxed(1, base + DML_CONSUMER_START);
102 /* make sure the dml is configured before dma is triggered */
107 static int of_get_dml_pipe_index(struct device_node *np, const char *name)
110 struct of_phandle_args dma_spec;
112 index = of_property_match_string(np, "dma-names", name);
117 if (of_parse_phandle_with_args(np, "dmas", "#dma-cells", index,
121 if (dma_spec.args_count)
122 return dma_spec.args[0];
127 /* Initialize the dml hardware connected to SD Card controller */
128 static int qcom_dma_setup(struct mmci_host *host)
132 int consumer_id, producer_id;
133 struct device_node *np = host->mmc->parent->of_node;
135 if (mmci_dmae_setup(host))
138 consumer_id = of_get_dml_pipe_index(np, "tx");
139 producer_id = of_get_dml_pipe_index(np, "rx");
141 if (producer_id < 0 || consumer_id < 0) {
142 mmci_dmae_release(host);
146 base = host->base + DML_OFFSET;
148 /* Reset the DML block */
149 writel_relaxed(1, base + DML_SW_RESET);
151 /* Disable the producer and consumer CRCI */
152 config = (PRODUCER_CRCI_DISABLE | CONSUMER_CRCI_DISABLE);
154 * Disable the bypass mode. Bypass mode will only be used
155 * if data transfer is to happen in PIO mode and don't
156 * want the BAM interface to connect with SDCC-DML.
160 * Disable direct mode as we don't DML to MASTER the AHB bus.
161 * BAM connected with DML should MASTER the AHB bus.
163 config &= ~DIRECT_MODE;
165 * Disable infinite mode transfer as we won't be doing any
166 * infinite size data transfers. All data transfer will be
167 * of finite data size.
169 config &= ~INFINITE_CONS_TRANS;
170 writel_relaxed(config, base + DML_CONFIG);
173 * Initialize the logical BAM pipe size for producer
176 writel_relaxed(PRODUCER_PIPE_LOGICAL_SIZE,
177 base + DML_PRODUCER_PIPE_LOGICAL_SIZE);
178 writel_relaxed(CONSUMER_PIPE_LOGICAL_SIZE,
179 base + DML_CONSUMER_PIPE_LOGICAL_SIZE);
181 /* Initialize Producer/consumer pipe id */
182 writel_relaxed(producer_id | (consumer_id << CONSUMER_PIPE_ID_SHFT),
185 /* Make sure dml initialization is finished */
191 static u32 qcom_get_dctrl_cfg(struct mmci_host *host)
193 return MCI_DPSM_ENABLE | (host->data->blksz << 4);
196 static struct mmci_host_ops qcom_variant_ops = {
197 .prep_data = mmci_dmae_prep_data,
198 .unprep_data = mmci_dmae_unprep_data,
199 .get_datactrl_cfg = qcom_get_dctrl_cfg,
200 .get_next_data = mmci_dmae_get_next_data,
201 .dma_setup = qcom_dma_setup,
202 .dma_release = mmci_dmae_release,
203 .dma_start = qcom_dma_start,
204 .dma_finalize = mmci_dmae_finalize,
205 .dma_error = mmci_dmae_error,
208 void qcom_variant_init(struct mmci_host *host)
210 host->ops = &qcom_variant_ops;