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 void dml_start_xfer(struct mmci_host
*host
, struct mmc_data
*data
)
60 void __iomem
*base
= host
->base
+ DML_OFFSET
;
62 if (data
->flags
& MMC_DATA_READ
) {
63 /* Read operation: configure DML for producer operation */
64 /* Set producer CRCI-x and disable consumer CRCI */
65 config
= readl_relaxed(base
+ DML_CONFIG
);
66 config
= (config
& ~PRODUCER_CRCI_MSK
) | PRODUCER_CRCI_X_SEL
;
67 config
= (config
& ~CONSUMER_CRCI_MSK
) | CONSUMER_CRCI_DISABLE
;
68 writel_relaxed(config
, base
+ DML_CONFIG
);
70 /* Set the Producer BAM block size */
71 writel_relaxed(data
->blksz
, base
+ DML_PRODUCER_BAM_BLOCK_SIZE
);
73 /* Set Producer BAM Transaction size */
74 writel_relaxed(data
->blocks
* data
->blksz
,
75 base
+ DML_PRODUCER_BAM_TRANS_SIZE
);
76 /* Set Producer Transaction End bit */
77 config
= readl_relaxed(base
+ DML_CONFIG
);
78 config
|= PRODUCER_TRANS_END_EN
;
79 writel_relaxed(config
, base
+ DML_CONFIG
);
80 /* Trigger producer */
81 writel_relaxed(1, base
+ DML_PRODUCER_START
);
83 /* Write operation: configure DML for consumer operation */
84 /* Set consumer CRCI-x and disable producer CRCI*/
85 config
= readl_relaxed(base
+ DML_CONFIG
);
86 config
= (config
& ~CONSUMER_CRCI_MSK
) | CONSUMER_CRCI_X_SEL
;
87 config
= (config
& ~PRODUCER_CRCI_MSK
) | PRODUCER_CRCI_DISABLE
;
88 writel_relaxed(config
, base
+ DML_CONFIG
);
89 /* Clear Producer Transaction End bit */
90 config
= readl_relaxed(base
+ DML_CONFIG
);
91 config
&= ~PRODUCER_TRANS_END_EN
;
92 writel_relaxed(config
, base
+ DML_CONFIG
);
93 /* Trigger consumer */
94 writel_relaxed(1, base
+ DML_CONSUMER_START
);
97 /* make sure the dml is configured before dma is triggered */
101 static int of_get_dml_pipe_index(struct device_node
*np
, const char *name
)
104 struct of_phandle_args dma_spec
;
106 index
= of_property_match_string(np
, "dma-names", name
);
111 if (of_parse_phandle_with_args(np
, "dmas", "#dma-cells", index
,
115 if (dma_spec
.args_count
)
116 return dma_spec
.args
[0];
121 /* Initialize the dml hardware connected to SD Card controller */
122 static int qcom_dma_setup(struct mmci_host
*host
)
126 int consumer_id
, producer_id
;
127 struct device_node
*np
= host
->mmc
->parent
->of_node
;
129 if (mmci_dmae_setup(host
))
132 consumer_id
= of_get_dml_pipe_index(np
, "tx");
133 producer_id
= of_get_dml_pipe_index(np
, "rx");
135 if (producer_id
< 0 || consumer_id
< 0) {
136 host
->variant
->qcom_dml
= false;
137 mmci_dmae_release(host
);
141 base
= host
->base
+ DML_OFFSET
;
143 /* Reset the DML block */
144 writel_relaxed(1, base
+ DML_SW_RESET
);
146 /* Disable the producer and consumer CRCI */
147 config
= (PRODUCER_CRCI_DISABLE
| CONSUMER_CRCI_DISABLE
);
149 * Disable the bypass mode. Bypass mode will only be used
150 * if data transfer is to happen in PIO mode and don't
151 * want the BAM interface to connect with SDCC-DML.
155 * Disable direct mode as we don't DML to MASTER the AHB bus.
156 * BAM connected with DML should MASTER the AHB bus.
158 config
&= ~DIRECT_MODE
;
160 * Disable infinite mode transfer as we won't be doing any
161 * infinite size data transfers. All data transfer will be
162 * of finite data size.
164 config
&= ~INFINITE_CONS_TRANS
;
165 writel_relaxed(config
, base
+ DML_CONFIG
);
168 * Initialize the logical BAM pipe size for producer
171 writel_relaxed(PRODUCER_PIPE_LOGICAL_SIZE
,
172 base
+ DML_PRODUCER_PIPE_LOGICAL_SIZE
);
173 writel_relaxed(CONSUMER_PIPE_LOGICAL_SIZE
,
174 base
+ DML_CONSUMER_PIPE_LOGICAL_SIZE
);
176 /* Initialize Producer/consumer pipe id */
177 writel_relaxed(producer_id
| (consumer_id
<< CONSUMER_PIPE_ID_SHFT
),
180 /* Make sure dml initialization is finished */
186 static struct mmci_host_ops qcom_variant_ops
= {
187 .prep_data
= mmci_dmae_prep_data
,
188 .unprep_data
= mmci_dmae_unprep_data
,
189 .get_next_data
= mmci_dmae_get_next_data
,
190 .dma_setup
= qcom_dma_setup
,
191 .dma_release
= mmci_dmae_release
,
192 .dma_start
= mmci_dmae_start
,
193 .dma_finalize
= mmci_dmae_finalize
,
194 .dma_error
= mmci_dmae_error
,
197 void qcom_variant_init(struct mmci_host
*host
)
199 host
->ops
= &qcom_variant_ops
;