aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/dma/coh901318.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index a724e6be1b4d..557e2272e5b3 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -72,6 +72,9 @@ struct coh901318_chan {
72 unsigned long nbr_active_done; 72 unsigned long nbr_active_done;
73 unsigned long busy; 73 unsigned long busy;
74 74
75 u32 runtime_addr;
76 u32 runtime_ctrl;
77
75 struct coh901318_base *base; 78 struct coh901318_base *base;
76}; 79};
77 80
@@ -190,6 +193,9 @@ static inline struct coh901318_chan *to_coh901318_chan(struct dma_chan *chan)
190static inline dma_addr_t 193static inline dma_addr_t
191cohc_dev_addr(struct coh901318_chan *cohc) 194cohc_dev_addr(struct coh901318_chan *cohc)
192{ 195{
196 /* Runtime supplied address will take precedence */
197 if (cohc->runtime_addr)
198 return cohc->runtime_addr;
193 return cohc->base->platform->chan_conf[cohc->id].dev_addr; 199 return cohc->base->platform->chan_conf[cohc->id].dev_addr;
194} 200}
195 201
@@ -1055,6 +1061,14 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
1055 1061
1056 params = cohc_chan_param(cohc); 1062 params = cohc_chan_param(cohc);
1057 config = params->config; 1063 config = params->config;
1064 /*
1065 * Add runtime-specific control on top, make
1066 * sure the bits you set per peripheral channel are
1067 * cleared in the default config from the platform.
1068 */
1069 ctrl_chained |= cohc->runtime_ctrl;
1070 ctrl_last |= cohc->runtime_ctrl;
1071 ctrl |= cohc->runtime_ctrl;
1058 1072
1059 if (direction == DMA_TO_DEVICE) { 1073 if (direction == DMA_TO_DEVICE) {
1060 u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE | 1074 u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE |
@@ -1113,6 +1127,12 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
1113 if (ret) 1127 if (ret)
1114 goto err_lli_fill; 1128 goto err_lli_fill;
1115 1129
1130 /*
1131 * Set the default ctrl for the channel to the one from the lli,
1132 * things may have changed due to odd buffer alignment etc.
1133 */
1134 coh901318_set_ctrl(cohc, lli->control);
1135
1116 COH_DBG(coh901318_list_print(cohc, lli)); 1136 COH_DBG(coh901318_list_print(cohc, lli));
1117 1137
1118 /* Pick a descriptor to handle this transfer */ 1138 /* Pick a descriptor to handle this transfer */
@@ -1175,6 +1195,146 @@ coh901318_issue_pending(struct dma_chan *chan)
1175 spin_unlock_irqrestore(&cohc->lock, flags); 1195 spin_unlock_irqrestore(&cohc->lock, flags);
1176} 1196}
1177 1197
1198/*
1199 * Here we wrap in the runtime dma control interface
1200 */
1201struct burst_table {
1202 int burst_8bit;
1203 int burst_16bit;
1204 int burst_32bit;
1205 u32 reg;
1206};
1207
1208static const struct burst_table burst_sizes[] = {
1209 {
1210 .burst_8bit = 64,
1211 .burst_16bit = 32,
1212 .burst_32bit = 16,
1213 .reg = COH901318_CX_CTRL_BURST_COUNT_64_BYTES,
1214 },
1215 {
1216 .burst_8bit = 48,
1217 .burst_16bit = 24,
1218 .burst_32bit = 12,
1219 .reg = COH901318_CX_CTRL_BURST_COUNT_48_BYTES,
1220 },
1221 {
1222 .burst_8bit = 32,
1223 .burst_16bit = 16,
1224 .burst_32bit = 8,
1225 .reg = COH901318_CX_CTRL_BURST_COUNT_32_BYTES,
1226 },
1227 {
1228 .burst_8bit = 16,
1229 .burst_16bit = 8,
1230 .burst_32bit = 4,
1231 .reg = COH901318_CX_CTRL_BURST_COUNT_16_BYTES,
1232 },
1233 {
1234 .burst_8bit = 8,
1235 .burst_16bit = 4,
1236 .burst_32bit = 2,
1237 .reg = COH901318_CX_CTRL_BURST_COUNT_8_BYTES,
1238 },
1239 {
1240 .burst_8bit = 4,
1241 .burst_16bit = 2,
1242 .burst_32bit = 1,
1243 .reg = COH901318_CX_CTRL_BURST_COUNT_4_BYTES,
1244 },
1245 {
1246 .burst_8bit = 2,
1247 .burst_16bit = 1,
1248 .burst_32bit = 0,
1249 .reg = COH901318_CX_CTRL_BURST_COUNT_2_BYTES,
1250 },
1251 {
1252 .burst_8bit = 1,
1253 .burst_16bit = 0,
1254 .burst_32bit = 0,
1255 .reg = COH901318_CX_CTRL_BURST_COUNT_1_BYTE,
1256 },
1257};
1258
1259static void coh901318_dma_set_runtimeconfig(struct dma_chan *chan,
1260 struct dma_slave_config *config)
1261{
1262 struct coh901318_chan *cohc = to_coh901318_chan(chan);
1263 dma_addr_t addr;
1264 enum dma_slave_buswidth addr_width;
1265 u32 maxburst;
1266 u32 runtime_ctrl = 0;
1267 int i = 0;
1268
1269 /* We only support mem to per or per to mem transfers */
1270 if (config->direction == DMA_FROM_DEVICE) {
1271 addr = config->src_addr;
1272 addr_width = config->src_addr_width;
1273 maxburst = config->src_maxburst;
1274 } else if (config->direction == DMA_TO_DEVICE) {
1275 addr = config->dst_addr;
1276 addr_width = config->dst_addr_width;
1277 maxburst = config->dst_maxburst;
1278 } else {
1279 dev_err(COHC_2_DEV(cohc), "illegal channel mode\n");
1280 return;
1281 }
1282
1283 dev_dbg(COHC_2_DEV(cohc), "configure channel for %d byte transfers\n",
1284 addr_width);
1285 switch (addr_width) {
1286 case DMA_SLAVE_BUSWIDTH_1_BYTE:
1287 runtime_ctrl |=
1288 COH901318_CX_CTRL_SRC_BUS_SIZE_8_BITS |
1289 COH901318_CX_CTRL_DST_BUS_SIZE_8_BITS;
1290
1291 while (i < ARRAY_SIZE(burst_sizes)) {
1292 if (burst_sizes[i].burst_8bit <= maxburst)
1293 break;
1294 i++;
1295 }
1296
1297 break;
1298 case DMA_SLAVE_BUSWIDTH_2_BYTES:
1299 runtime_ctrl |=
1300 COH901318_CX_CTRL_SRC_BUS_SIZE_16_BITS |
1301 COH901318_CX_CTRL_DST_BUS_SIZE_16_BITS;
1302
1303 while (i < ARRAY_SIZE(burst_sizes)) {
1304 if (burst_sizes[i].burst_16bit <= maxburst)
1305 break;
1306 i++;
1307 }
1308
1309 break;
1310 case DMA_SLAVE_BUSWIDTH_4_BYTES:
1311 /* Direction doesn't matter here, it's 32/32 bits */
1312 runtime_ctrl |=
1313 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
1314 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS;
1315
1316 while (i < ARRAY_SIZE(burst_sizes)) {
1317 if (burst_sizes[i].burst_32bit <= maxburst)
1318 break;
1319 i++;
1320 }
1321
1322 break;
1323 default:
1324 dev_err(COHC_2_DEV(cohc),
1325 "bad runtimeconfig: alien address width\n");
1326 return;
1327 }
1328
1329 runtime_ctrl |= burst_sizes[i].reg;
1330 dev_dbg(COHC_2_DEV(cohc),
1331 "selected burst size %d bytes for address width %d bytes, maxburst %d\n",
1332 burst_sizes[i].burst_8bit, addr_width, maxburst);
1333
1334 cohc->runtime_addr = addr;
1335 cohc->runtime_ctrl = runtime_ctrl;
1336}
1337
1178static int 1338static int
1179coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, 1339coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
1180 unsigned long arg) 1340 unsigned long arg)
@@ -1184,6 +1344,14 @@ coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
1184 struct coh901318_desc *cohd; 1344 struct coh901318_desc *cohd;
1185 void __iomem *virtbase = cohc->base->virtbase; 1345 void __iomem *virtbase = cohc->base->virtbase;
1186 1346
1347 if (cmd == DMA_SLAVE_CONFIG) {
1348 struct dma_slave_config *config =
1349 (struct dma_slave_config *) arg;
1350
1351 coh901318_dma_set_runtimeconfig(chan, config);
1352 return 0;
1353 }
1354
1187 if (cmd == DMA_PAUSE) { 1355 if (cmd == DMA_PAUSE) {
1188 coh901318_pause(chan); 1356 coh901318_pause(chan);
1189 return 0; 1357 return 0;
@@ -1240,6 +1408,7 @@ coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
1240 1408
1241 return 0; 1409 return 0;
1242} 1410}
1411
1243void coh901318_base_init(struct dma_device *dma, const int *pick_chans, 1412void coh901318_base_init(struct dma_device *dma, const int *pick_chans,
1244 struct coh901318_base *base) 1413 struct coh901318_base *base)
1245{ 1414{