diff options
Diffstat (limited to 'drivers/dma/ste_dma40.c')
-rw-r--r-- | drivers/dma/ste_dma40.c | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 3f76cd9af7c3..fab68a553205 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c | |||
@@ -175,6 +175,7 @@ struct d40_base; | |||
175 | * @active: Active descriptor. | 175 | * @active: Active descriptor. |
176 | * @queue: Queued jobs. | 176 | * @queue: Queued jobs. |
177 | * @dma_cfg: The client configuration of this dma channel. | 177 | * @dma_cfg: The client configuration of this dma channel. |
178 | * @configured: whether the dma_cfg configuration is valid | ||
178 | * @base: Pointer to the device instance struct. | 179 | * @base: Pointer to the device instance struct. |
179 | * @src_def_cfg: Default cfg register setting for src. | 180 | * @src_def_cfg: Default cfg register setting for src. |
180 | * @dst_def_cfg: Default cfg register setting for dst. | 181 | * @dst_def_cfg: Default cfg register setting for dst. |
@@ -198,6 +199,7 @@ struct d40_chan { | |||
198 | struct list_head active; | 199 | struct list_head active; |
199 | struct list_head queue; | 200 | struct list_head queue; |
200 | struct stedma40_chan_cfg dma_cfg; | 201 | struct stedma40_chan_cfg dma_cfg; |
202 | bool configured; | ||
201 | struct d40_base *base; | 203 | struct d40_base *base; |
202 | /* Default register configurations */ | 204 | /* Default register configurations */ |
203 | u32 src_def_cfg; | 205 | u32 src_def_cfg; |
@@ -691,6 +693,31 @@ static u32 d40_chan_has_events(struct d40_chan *d40c) | |||
691 | return val; | 693 | return val; |
692 | } | 694 | } |
693 | 695 | ||
696 | static u32 d40_get_prmo(struct d40_chan *d40c) | ||
697 | { | ||
698 | static const unsigned int phy_map[] = { | ||
699 | [STEDMA40_PCHAN_BASIC_MODE] | ||
700 | = D40_DREG_PRMO_PCHAN_BASIC, | ||
701 | [STEDMA40_PCHAN_MODULO_MODE] | ||
702 | = D40_DREG_PRMO_PCHAN_MODULO, | ||
703 | [STEDMA40_PCHAN_DOUBLE_DST_MODE] | ||
704 | = D40_DREG_PRMO_PCHAN_DOUBLE_DST, | ||
705 | }; | ||
706 | static const unsigned int log_map[] = { | ||
707 | [STEDMA40_LCHAN_SRC_PHY_DST_LOG] | ||
708 | = D40_DREG_PRMO_LCHAN_SRC_PHY_DST_LOG, | ||
709 | [STEDMA40_LCHAN_SRC_LOG_DST_PHY] | ||
710 | = D40_DREG_PRMO_LCHAN_SRC_LOG_DST_PHY, | ||
711 | [STEDMA40_LCHAN_SRC_LOG_DST_LOG] | ||
712 | = D40_DREG_PRMO_LCHAN_SRC_LOG_DST_LOG, | ||
713 | }; | ||
714 | |||
715 | if (d40c->log_num == D40_PHY_CHAN) | ||
716 | return phy_map[d40c->dma_cfg.mode_opt]; | ||
717 | else | ||
718 | return log_map[d40c->dma_cfg.mode_opt]; | ||
719 | } | ||
720 | |||
694 | static void d40_config_write(struct d40_chan *d40c) | 721 | static void d40_config_write(struct d40_chan *d40c) |
695 | { | 722 | { |
696 | u32 addr_base; | 723 | u32 addr_base; |
@@ -704,8 +731,7 @@ static void d40_config_write(struct d40_chan *d40c) | |||
704 | writel(var, d40c->base->virtbase + D40_DREG_PRMSE + addr_base); | 731 | writel(var, d40c->base->virtbase + D40_DREG_PRMSE + addr_base); |
705 | 732 | ||
706 | /* Setup operational mode option register */ | 733 | /* Setup operational mode option register */ |
707 | var = ((d40c->dma_cfg.channel_type >> STEDMA40_INFO_CH_MODE_OPT_POS) & | 734 | var = d40_get_prmo(d40c) << D40_CHAN_POS(d40c->phy_chan->num); |
708 | 0x3) << D40_CHAN_POS(d40c->phy_chan->num); | ||
709 | 735 | ||
710 | writel(var, d40c->base->virtbase + D40_DREG_PRMOE + addr_base); | 736 | writel(var, d40c->base->virtbase + D40_DREG_PRMOE + addr_base); |
711 | 737 | ||
@@ -1149,8 +1175,7 @@ static int d40_validate_conf(struct d40_chan *d40c, | |||
1149 | int res = 0; | 1175 | int res = 0; |
1150 | u32 dst_event_group = D40_TYPE_TO_GROUP(conf->dst_dev_type); | 1176 | u32 dst_event_group = D40_TYPE_TO_GROUP(conf->dst_dev_type); |
1151 | u32 src_event_group = D40_TYPE_TO_GROUP(conf->src_dev_type); | 1177 | u32 src_event_group = D40_TYPE_TO_GROUP(conf->src_dev_type); |
1152 | bool is_log = (conf->channel_type & STEDMA40_CHANNEL_IN_OPER_MODE) | 1178 | bool is_log = conf->mode == STEDMA40_MODE_LOGICAL; |
1153 | == STEDMA40_CHANNEL_IN_LOG_MODE; | ||
1154 | 1179 | ||
1155 | if (!conf->dir) { | 1180 | if (!conf->dir) { |
1156 | dev_err(&d40c->chan.dev->device, "[%s] Invalid direction.\n", | 1181 | dev_err(&d40c->chan.dev->device, "[%s] Invalid direction.\n", |
@@ -1314,10 +1339,7 @@ static int d40_allocate_channel(struct d40_chan *d40c) | |||
1314 | int j; | 1339 | int j; |
1315 | int log_num; | 1340 | int log_num; |
1316 | bool is_src; | 1341 | bool is_src; |
1317 | bool is_log = (d40c->dma_cfg.channel_type & | 1342 | bool is_log = d40c->dma_cfg.mode == STEDMA40_MODE_LOGICAL; |
1318 | STEDMA40_CHANNEL_IN_OPER_MODE) | ||
1319 | == STEDMA40_CHANNEL_IN_LOG_MODE; | ||
1320 | |||
1321 | 1343 | ||
1322 | phys = d40c->base->phy_res; | 1344 | phys = d40c->base->phy_res; |
1323 | 1345 | ||
@@ -1518,8 +1540,7 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
1518 | return res; | 1540 | return res; |
1519 | } | 1541 | } |
1520 | d40c->phy_chan = NULL; | 1542 | d40c->phy_chan = NULL; |
1521 | /* Invalidate channel type */ | 1543 | d40c->configured = false; |
1522 | d40c->dma_cfg.channel_type = 0; | ||
1523 | d40c->base->lookup_phy_chans[phy->num] = NULL; | 1544 | d40c->base->lookup_phy_chans[phy->num] = NULL; |
1524 | 1545 | ||
1525 | return 0; | 1546 | return 0; |
@@ -1704,6 +1725,9 @@ bool stedma40_filter(struct dma_chan *chan, void *data) | |||
1704 | } else | 1725 | } else |
1705 | err = d40_config_memcpy(d40c); | 1726 | err = d40_config_memcpy(d40c); |
1706 | 1727 | ||
1728 | if (!err) | ||
1729 | d40c->configured = true; | ||
1730 | |||
1707 | return err == 0; | 1731 | return err == 0; |
1708 | } | 1732 | } |
1709 | EXPORT_SYMBOL(stedma40_filter); | 1733 | EXPORT_SYMBOL(stedma40_filter); |
@@ -1720,12 +1744,8 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) | |||
1720 | 1744 | ||
1721 | d40c->completed = chan->cookie = 1; | 1745 | d40c->completed = chan->cookie = 1; |
1722 | 1746 | ||
1723 | /* | 1747 | /* If no dma configuration is set use default configuration (memcpy) */ |
1724 | * If no dma configuration is set (channel_type == 0) | 1748 | if (!d40c->configured) { |
1725 | * use default configuration (memcpy) | ||
1726 | */ | ||
1727 | if (d40c->dma_cfg.channel_type == 0) { | ||
1728 | |||
1729 | err = d40_config_memcpy(d40c); | 1749 | err = d40_config_memcpy(d40c); |
1730 | if (err) { | 1750 | if (err) { |
1731 | dev_err(&d40c->chan.dev->device, | 1751 | dev_err(&d40c->chan.dev->device, |
@@ -2231,11 +2251,11 @@ static void d40_set_runtime_config(struct dma_chan *chan, | |||
2231 | /* Set up all the endpoint configs */ | 2251 | /* Set up all the endpoint configs */ |
2232 | cfg->src_info.data_width = addr_width; | 2252 | cfg->src_info.data_width = addr_width; |
2233 | cfg->src_info.psize = psize; | 2253 | cfg->src_info.psize = psize; |
2234 | cfg->src_info.endianess = STEDMA40_LITTLE_ENDIAN; | 2254 | cfg->src_info.big_endian = false; |
2235 | cfg->src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL; | 2255 | cfg->src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL; |
2236 | cfg->dst_info.data_width = addr_width; | 2256 | cfg->dst_info.data_width = addr_width; |
2237 | cfg->dst_info.psize = psize; | 2257 | cfg->dst_info.psize = psize; |
2238 | cfg->dst_info.endianess = STEDMA40_LITTLE_ENDIAN; | 2258 | cfg->dst_info.big_endian = false; |
2239 | cfg->dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL; | 2259 | cfg->dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL; |
2240 | 2260 | ||
2241 | /* Fill in register values */ | 2261 | /* Fill in register values */ |