Linux Audio

Check our new training course

Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2// Copyright (C) 2007-2008 Atmel Corporation
  3// Copyright (C) 2010-2011 ST Microelectronics
  4// Copyright (C) 2013,2018 Intel Corporation
  5
  6#include <linux/bitops.h>
  7#include <linux/dmaengine.h>
  8#include <linux/errno.h>
  9#include <linux/slab.h>
 10#include <linux/types.h>
 11
 12#include "internal.h"
 13
 14static void dw_dma_initialize_chan(struct dw_dma_chan *dwc)
 15{
 16	struct dw_dma *dw = to_dw_dma(dwc->chan.device);
 17	u32 cfghi = is_slave_direction(dwc->direction) ? 0 : DWC_CFGH_FIFO_MODE;
 18	u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority);
 19	bool hs_polarity = dwc->dws.hs_polarity;
 20
 21	cfghi |= DWC_CFGH_DST_PER(dwc->dws.dst_id);
 22	cfghi |= DWC_CFGH_SRC_PER(dwc->dws.src_id);
 23	cfghi |= DWC_CFGH_PROTCTL(dw->pdata->protctl);
 24
 25	/* Set polarity of handshake interface */
 26	cfglo |= hs_polarity ? DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL : 0;
 27
 28	channel_writel(dwc, CFG_LO, cfglo);
 29	channel_writel(dwc, CFG_HI, cfghi);
 30}
 31
 32static void dw_dma_suspend_chan(struct dw_dma_chan *dwc, bool drain)
 33{
 34	u32 cfglo = channel_readl(dwc, CFG_LO);
 35
 36	channel_writel(dwc, CFG_LO, cfglo | DWC_CFGL_CH_SUSP);
 37}
 38
 39static void dw_dma_resume_chan(struct dw_dma_chan *dwc, bool drain)
 40{
 41	u32 cfglo = channel_readl(dwc, CFG_LO);
 42
 43	channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP);
 44}
 45
 46static u32 dw_dma_bytes2block(struct dw_dma_chan *dwc,
 47			      size_t bytes, unsigned int width, size_t *len)
 48{
 49	u32 block;
 50
 51	if ((bytes >> width) > dwc->block_size) {
 52		block = dwc->block_size;
 53		*len = dwc->block_size << width;
 54	} else {
 55		block = bytes >> width;
 56		*len = bytes;
 57	}
 58
 59	return block;
 60}
 61
 62static size_t dw_dma_block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width)
 63{
 64	return DWC_CTLH_BLOCK_TS(block) << width;
 65}
 66
 
 
 
 
 
 
 
 
 
 67static u32 dw_dma_prepare_ctllo(struct dw_dma_chan *dwc)
 68{
 69	struct dma_slave_config	*sconfig = &dwc->dma_sconfig;
 70	u8 smsize = (dwc->direction == DMA_DEV_TO_MEM) ? sconfig->src_maxburst : 0;
 71	u8 dmsize = (dwc->direction == DMA_MEM_TO_DEV) ? sconfig->dst_maxburst : 0;
 72	u8 p_master = dwc->dws.p_master;
 73	u8 m_master = dwc->dws.m_master;
 74	u8 dms = (dwc->direction == DMA_MEM_TO_DEV) ? p_master : m_master;
 75	u8 sms = (dwc->direction == DMA_DEV_TO_MEM) ? p_master : m_master;
 
 
 
 
 
 
 
 
 
 76
 77	return DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN |
 78	       DWC_CTLL_DST_MSIZE(dmsize) | DWC_CTLL_SRC_MSIZE(smsize) |
 79	       DWC_CTLL_DMS(dms) | DWC_CTLL_SMS(sms);
 80}
 81
 82static void dw_dma_encode_maxburst(struct dw_dma_chan *dwc, u32 *maxburst)
 83{
 84	/*
 85	 * Fix burst size according to dw_dmac. We need to convert them as:
 86	 * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
 87	 */
 88	*maxburst = *maxburst > 1 ? fls(*maxburst) - 2 : 0;
 89}
 90
 91static void dw_dma_set_device_name(struct dw_dma *dw, int id)
 92{
 93	snprintf(dw->name, sizeof(dw->name), "dw:dmac%d", id);
 94}
 95
 96static void dw_dma_disable(struct dw_dma *dw)
 97{
 98	do_dw_dma_off(dw);
 99}
100
101static void dw_dma_enable(struct dw_dma *dw)
102{
103	do_dw_dma_on(dw);
104}
105
106int dw_dma_probe(struct dw_dma_chip *chip)
107{
108	struct dw_dma *dw;
109
110	dw = devm_kzalloc(chip->dev, sizeof(*dw), GFP_KERNEL);
111	if (!dw)
112		return -ENOMEM;
113
114	/* Channel operations */
115	dw->initialize_chan = dw_dma_initialize_chan;
116	dw->suspend_chan = dw_dma_suspend_chan;
117	dw->resume_chan = dw_dma_resume_chan;
118	dw->prepare_ctllo = dw_dma_prepare_ctllo;
119	dw->encode_maxburst = dw_dma_encode_maxburst;
120	dw->bytes2block = dw_dma_bytes2block;
121	dw->block2bytes = dw_dma_block2bytes;
122
123	/* Device operations */
124	dw->set_device_name = dw_dma_set_device_name;
125	dw->disable = dw_dma_disable;
126	dw->enable = dw_dma_enable;
127
128	chip->dw = dw;
129	return do_dma_probe(chip);
130}
131EXPORT_SYMBOL_GPL(dw_dma_probe);
132
133int dw_dma_remove(struct dw_dma_chip *chip)
134{
135	return do_dma_remove(chip);
136}
137EXPORT_SYMBOL_GPL(dw_dma_remove);
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2// Copyright (C) 2007-2008 Atmel Corporation
  3// Copyright (C) 2010-2011 ST Microelectronics
  4// Copyright (C) 2013,2018 Intel Corporation
  5
  6#include <linux/bitops.h>
  7#include <linux/dmaengine.h>
  8#include <linux/errno.h>
  9#include <linux/slab.h>
 10#include <linux/types.h>
 11
 12#include "internal.h"
 13
 14static void dw_dma_initialize_chan(struct dw_dma_chan *dwc)
 15{
 16	struct dw_dma *dw = to_dw_dma(dwc->chan.device);
 17	u32 cfghi = is_slave_direction(dwc->direction) ? 0 : DWC_CFGH_FIFO_MODE;
 18	u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority);
 19	bool hs_polarity = dwc->dws.hs_polarity;
 20
 21	cfghi |= DWC_CFGH_DST_PER(dwc->dws.dst_id);
 22	cfghi |= DWC_CFGH_SRC_PER(dwc->dws.src_id);
 23	cfghi |= DWC_CFGH_PROTCTL(dw->pdata->protctl);
 24
 25	/* Set polarity of handshake interface */
 26	cfglo |= hs_polarity ? DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL : 0;
 27
 28	channel_writel(dwc, CFG_LO, cfglo);
 29	channel_writel(dwc, CFG_HI, cfghi);
 30}
 31
 32static void dw_dma_suspend_chan(struct dw_dma_chan *dwc, bool drain)
 33{
 34	u32 cfglo = channel_readl(dwc, CFG_LO);
 35
 36	channel_writel(dwc, CFG_LO, cfglo | DWC_CFGL_CH_SUSP);
 37}
 38
 39static void dw_dma_resume_chan(struct dw_dma_chan *dwc, bool drain)
 40{
 41	u32 cfglo = channel_readl(dwc, CFG_LO);
 42
 43	channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP);
 44}
 45
 46static u32 dw_dma_bytes2block(struct dw_dma_chan *dwc,
 47			      size_t bytes, unsigned int width, size_t *len)
 48{
 49	u32 block;
 50
 51	if ((bytes >> width) > dwc->block_size) {
 52		block = dwc->block_size;
 53		*len = dwc->block_size << width;
 54	} else {
 55		block = bytes >> width;
 56		*len = bytes;
 57	}
 58
 59	return block;
 60}
 61
 62static size_t dw_dma_block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width)
 63{
 64	return DWC_CTLH_BLOCK_TS(block) << width;
 65}
 66
 67static inline u8 dw_dma_encode_maxburst(u32 maxburst)
 68{
 69	/*
 70	 * Fix burst size according to dw_dmac. We need to convert them as:
 71	 * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
 72	 */
 73	return maxburst > 1 ? fls(maxburst) - 2 : 0;
 74}
 75
 76static u32 dw_dma_prepare_ctllo(struct dw_dma_chan *dwc)
 77{
 78	struct dma_slave_config	*sconfig = &dwc->dma_sconfig;
 79	u8 smsize = 0, dmsize = 0;
 80	u8 sms, dms;
 81
 82	if (dwc->direction == DMA_MEM_TO_DEV) {
 83		sms = dwc->dws.m_master;
 84		dms = dwc->dws.p_master;
 85		dmsize = dw_dma_encode_maxburst(sconfig->dst_maxburst);
 86	} else if (dwc->direction == DMA_DEV_TO_MEM) {
 87		sms = dwc->dws.p_master;
 88		dms = dwc->dws.m_master;
 89		smsize = dw_dma_encode_maxburst(sconfig->src_maxburst);
 90	} else /* DMA_MEM_TO_MEM */ {
 91		sms = dwc->dws.m_master;
 92		dms = dwc->dws.m_master;
 93	}
 94
 95	return DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN |
 96	       DWC_CTLL_DST_MSIZE(dmsize) | DWC_CTLL_SRC_MSIZE(smsize) |
 97	       DWC_CTLL_DMS(dms) | DWC_CTLL_SMS(sms);
 98}
 99
 
 
 
 
 
 
 
 
 
100static void dw_dma_set_device_name(struct dw_dma *dw, int id)
101{
102	snprintf(dw->name, sizeof(dw->name), "dw:dmac%d", id);
103}
104
105static void dw_dma_disable(struct dw_dma *dw)
106{
107	do_dw_dma_off(dw);
108}
109
110static void dw_dma_enable(struct dw_dma *dw)
111{
112	do_dw_dma_on(dw);
113}
114
115int dw_dma_probe(struct dw_dma_chip *chip)
116{
117	struct dw_dma *dw;
118
119	dw = devm_kzalloc(chip->dev, sizeof(*dw), GFP_KERNEL);
120	if (!dw)
121		return -ENOMEM;
122
123	/* Channel operations */
124	dw->initialize_chan = dw_dma_initialize_chan;
125	dw->suspend_chan = dw_dma_suspend_chan;
126	dw->resume_chan = dw_dma_resume_chan;
127	dw->prepare_ctllo = dw_dma_prepare_ctllo;
 
128	dw->bytes2block = dw_dma_bytes2block;
129	dw->block2bytes = dw_dma_block2bytes;
130
131	/* Device operations */
132	dw->set_device_name = dw_dma_set_device_name;
133	dw->disable = dw_dma_disable;
134	dw->enable = dw_dma_enable;
135
136	chip->dw = dw;
137	return do_dma_probe(chip);
138}
139EXPORT_SYMBOL_GPL(dw_dma_probe);
140
141int dw_dma_remove(struct dw_dma_chip *chip)
142{
143	return do_dma_remove(chip);
144}
145EXPORT_SYMBOL_GPL(dw_dma_remove);