0001
0002
0003
0004
0005
0006 #include <linux/of.h>
0007 #include <linux/of_dma.h>
0008 #include <linux/bitops.h>
0009 #include <linux/mmc/host.h>
0010 #include <linux/mmc/card.h>
0011 #include "mmci.h"
0012
0013
0014 #define DML_CONFIG 0x00
0015 #define PRODUCER_CRCI_MSK GENMASK(1, 0)
0016 #define PRODUCER_CRCI_DISABLE 0
0017 #define PRODUCER_CRCI_X_SEL BIT(0)
0018 #define PRODUCER_CRCI_Y_SEL BIT(1)
0019 #define CONSUMER_CRCI_MSK GENMASK(3, 2)
0020 #define CONSUMER_CRCI_DISABLE 0
0021 #define CONSUMER_CRCI_X_SEL BIT(2)
0022 #define CONSUMER_CRCI_Y_SEL BIT(3)
0023 #define PRODUCER_TRANS_END_EN BIT(4)
0024 #define BYPASS BIT(16)
0025 #define DIRECT_MODE BIT(17)
0026 #define INFINITE_CONS_TRANS BIT(18)
0027
0028 #define DML_SW_RESET 0x08
0029 #define DML_PRODUCER_START 0x0c
0030 #define DML_CONSUMER_START 0x10
0031 #define DML_PRODUCER_PIPE_LOGICAL_SIZE 0x14
0032 #define DML_CONSUMER_PIPE_LOGICAL_SIZE 0x18
0033 #define DML_PIPE_ID 0x1c
0034 #define PRODUCER_PIPE_ID_SHFT 0
0035 #define PRODUCER_PIPE_ID_MSK GENMASK(4, 0)
0036 #define CONSUMER_PIPE_ID_SHFT 16
0037 #define CONSUMER_PIPE_ID_MSK GENMASK(20, 16)
0038
0039 #define DML_PRODUCER_BAM_BLOCK_SIZE 0x24
0040 #define DML_PRODUCER_BAM_TRANS_SIZE 0x28
0041
0042
0043 #define PRODUCER_PIPE_LOGICAL_SIZE 4096
0044 #define CONSUMER_PIPE_LOGICAL_SIZE 4096
0045
0046 #define DML_OFFSET 0x800
0047
0048 static int qcom_dma_start(struct mmci_host *host, unsigned int *datactrl)
0049 {
0050 u32 config;
0051 void __iomem *base = host->base + DML_OFFSET;
0052 struct mmc_data *data = host->data;
0053 int ret = mmci_dmae_start(host, datactrl);
0054
0055 if (ret)
0056 return ret;
0057
0058 if (data->flags & MMC_DATA_READ) {
0059
0060
0061 config = readl_relaxed(base + DML_CONFIG);
0062 config = (config & ~PRODUCER_CRCI_MSK) | PRODUCER_CRCI_X_SEL;
0063 config = (config & ~CONSUMER_CRCI_MSK) | CONSUMER_CRCI_DISABLE;
0064 writel_relaxed(config, base + DML_CONFIG);
0065
0066
0067 writel_relaxed(data->blksz, base + DML_PRODUCER_BAM_BLOCK_SIZE);
0068
0069
0070 writel_relaxed(data->blocks * data->blksz,
0071 base + DML_PRODUCER_BAM_TRANS_SIZE);
0072
0073 config = readl_relaxed(base + DML_CONFIG);
0074 config |= PRODUCER_TRANS_END_EN;
0075 writel_relaxed(config, base + DML_CONFIG);
0076
0077 writel_relaxed(1, base + DML_PRODUCER_START);
0078 } else {
0079
0080
0081 config = readl_relaxed(base + DML_CONFIG);
0082 config = (config & ~CONSUMER_CRCI_MSK) | CONSUMER_CRCI_X_SEL;
0083 config = (config & ~PRODUCER_CRCI_MSK) | PRODUCER_CRCI_DISABLE;
0084 writel_relaxed(config, base + DML_CONFIG);
0085
0086 config = readl_relaxed(base + DML_CONFIG);
0087 config &= ~PRODUCER_TRANS_END_EN;
0088 writel_relaxed(config, base + DML_CONFIG);
0089
0090 writel_relaxed(1, base + DML_CONSUMER_START);
0091 }
0092
0093
0094 wmb();
0095 return 0;
0096 }
0097
0098 static int of_get_dml_pipe_index(struct device_node *np, const char *name)
0099 {
0100 int index;
0101 struct of_phandle_args dma_spec;
0102
0103 index = of_property_match_string(np, "dma-names", name);
0104
0105 if (index < 0)
0106 return -ENODEV;
0107
0108 if (of_parse_phandle_with_args(np, "dmas", "#dma-cells", index,
0109 &dma_spec))
0110 return -ENODEV;
0111
0112 if (dma_spec.args_count)
0113 return dma_spec.args[0];
0114
0115 return -ENODEV;
0116 }
0117
0118
0119 static int qcom_dma_setup(struct mmci_host *host)
0120 {
0121 u32 config;
0122 void __iomem *base;
0123 int consumer_id, producer_id;
0124 struct device_node *np = host->mmc->parent->of_node;
0125
0126 if (mmci_dmae_setup(host))
0127 return -EINVAL;
0128
0129 consumer_id = of_get_dml_pipe_index(np, "tx");
0130 producer_id = of_get_dml_pipe_index(np, "rx");
0131
0132 if (producer_id < 0 || consumer_id < 0) {
0133 mmci_dmae_release(host);
0134 return -EINVAL;
0135 }
0136
0137 base = host->base + DML_OFFSET;
0138
0139
0140 writel_relaxed(1, base + DML_SW_RESET);
0141
0142
0143 config = (PRODUCER_CRCI_DISABLE | CONSUMER_CRCI_DISABLE);
0144
0145
0146
0147
0148
0149 config &= ~BYPASS;
0150
0151
0152
0153
0154 config &= ~DIRECT_MODE;
0155
0156
0157
0158
0159
0160 config &= ~INFINITE_CONS_TRANS;
0161 writel_relaxed(config, base + DML_CONFIG);
0162
0163
0164
0165
0166
0167 writel_relaxed(PRODUCER_PIPE_LOGICAL_SIZE,
0168 base + DML_PRODUCER_PIPE_LOGICAL_SIZE);
0169 writel_relaxed(CONSUMER_PIPE_LOGICAL_SIZE,
0170 base + DML_CONSUMER_PIPE_LOGICAL_SIZE);
0171
0172
0173 writel_relaxed(producer_id | (consumer_id << CONSUMER_PIPE_ID_SHFT),
0174 base + DML_PIPE_ID);
0175
0176
0177 mb();
0178
0179 return 0;
0180 }
0181
0182 static u32 qcom_get_dctrl_cfg(struct mmci_host *host)
0183 {
0184 return MCI_DPSM_ENABLE | (host->data->blksz << 4);
0185 }
0186
0187 static struct mmci_host_ops qcom_variant_ops = {
0188 .prep_data = mmci_dmae_prep_data,
0189 .unprep_data = mmci_dmae_unprep_data,
0190 .get_datactrl_cfg = qcom_get_dctrl_cfg,
0191 .get_next_data = mmci_dmae_get_next_data,
0192 .dma_setup = qcom_dma_setup,
0193 .dma_release = mmci_dmae_release,
0194 .dma_start = qcom_dma_start,
0195 .dma_finalize = mmci_dmae_finalize,
0196 .dma_error = mmci_dmae_error,
0197 };
0198
0199 void qcom_variant_init(struct mmci_host *host)
0200 {
0201 host->ops = &qcom_variant_ops;
0202 }