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 int dml_hw_init(struct mmci_host
*host
, struct device_node
*np
)
126 int consumer_id
, producer_id
;
128 consumer_id
= of_get_dml_pipe_index(np
, "tx");
129 producer_id
= of_get_dml_pipe_index(np
, "rx");
131 if (producer_id
< 0 || consumer_id
< 0)
134 base
= host
->base
+ DML_OFFSET
;
136 /* Reset the DML block */
137 writel_relaxed(1, base
+ DML_SW_RESET
);
139 /* Disable the producer and consumer CRCI */
140 config
= (PRODUCER_CRCI_DISABLE
| CONSUMER_CRCI_DISABLE
);
142 * Disable the bypass mode. Bypass mode will only be used
143 * if data transfer is to happen in PIO mode and don't
144 * want the BAM interface to connect with SDCC-DML.
148 * Disable direct mode as we don't DML to MASTER the AHB bus.
149 * BAM connected with DML should MASTER the AHB bus.
151 config
&= ~DIRECT_MODE
;
153 * Disable infinite mode transfer as we won't be doing any
154 * infinite size data transfers. All data transfer will be
155 * of finite data size.
157 config
&= ~INFINITE_CONS_TRANS
;
158 writel_relaxed(config
, base
+ DML_CONFIG
);
161 * Initialize the logical BAM pipe size for producer
164 writel_relaxed(PRODUCER_PIPE_LOGICAL_SIZE
,
165 base
+ DML_PRODUCER_PIPE_LOGICAL_SIZE
);
166 writel_relaxed(CONSUMER_PIPE_LOGICAL_SIZE
,
167 base
+ DML_CONSUMER_PIPE_LOGICAL_SIZE
);
169 /* Initialize Producer/consumer pipe id */
170 writel_relaxed(producer_id
| (consumer_id
<< CONSUMER_PIPE_ID_SHFT
),
173 /* Make sure dml intialization is finished */