1007 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2019 Spreadtrum Communications Inc.3 4#include <linux/errno.h>5#include <linux/interrupt.h>6#include <linux/io.h>7#include <linux/kernel.h>8#include <linux/module.h>9#include <linux/mutex.h>10#include <linux/of.h>11#include <linux/platform_device.h>12#include <linux/spinlock.h>13 14#include "sprd-mcdt.h"15 16/* MCDT registers definition */17#define MCDT_CH0_TXD 0x018#define MCDT_CH0_RXD 0x2819#define MCDT_DAC0_WTMK 0x6020#define MCDT_ADC0_WTMK 0x8821#define MCDT_DMA_EN 0xb022 23#define MCDT_INT_EN0 0xb424#define MCDT_INT_EN1 0xb825#define MCDT_INT_EN2 0xbc26 27#define MCDT_INT_CLR0 0xc028#define MCDT_INT_CLR1 0xc429#define MCDT_INT_CLR2 0xc830 31#define MCDT_INT_RAW1 0xcc32#define MCDT_INT_RAW2 0xd033#define MCDT_INT_RAW3 0xd434 35#define MCDT_INT_MSK1 0xd836#define MCDT_INT_MSK2 0xdc37#define MCDT_INT_MSK3 0xe038 39#define MCDT_DAC0_FIFO_ADDR_ST 0xe440#define MCDT_ADC0_FIFO_ADDR_ST 0xe841 42#define MCDT_CH_FIFO_ST0 0x13443#define MCDT_CH_FIFO_ST1 0x13844#define MCDT_CH_FIFO_ST2 0x13c45 46#define MCDT_INT_MSK_CFG0 0x14047#define MCDT_INT_MSK_CFG1 0x14448 49#define MCDT_DMA_CFG0 0x14850#define MCDT_FIFO_CLR 0x14c51#define MCDT_DMA_CFG1 0x15052#define MCDT_DMA_CFG2 0x15453#define MCDT_DMA_CFG3 0x15854#define MCDT_DMA_CFG4 0x15c55#define MCDT_DMA_CFG5 0x16056 57/* Channel water mark definition */58#define MCDT_CH_FIFO_AE_SHIFT 1659#define MCDT_CH_FIFO_AE_MASK GENMASK(24, 16)60#define MCDT_CH_FIFO_AF_MASK GENMASK(8, 0)61 62/* DMA channel select definition */63#define MCDT_DMA_CH0_SEL_MASK GENMASK(3, 0)64#define MCDT_DMA_CH0_SEL_SHIFT 065#define MCDT_DMA_CH1_SEL_MASK GENMASK(7, 4)66#define MCDT_DMA_CH1_SEL_SHIFT 467#define MCDT_DMA_CH2_SEL_MASK GENMASK(11, 8)68#define MCDT_DMA_CH2_SEL_SHIFT 869#define MCDT_DMA_CH3_SEL_MASK GENMASK(15, 12)70#define MCDT_DMA_CH3_SEL_SHIFT 1271#define MCDT_DMA_CH4_SEL_MASK GENMASK(19, 16)72#define MCDT_DMA_CH4_SEL_SHIFT 1673#define MCDT_DAC_DMA_SHIFT 1674 75/* DMA channel ACK select definition */76#define MCDT_DMA_ACK_SEL_MASK GENMASK(3, 0)77 78/* Channel FIFO definition */79#define MCDT_CH_FIFO_ADDR_SHIFT 1680#define MCDT_CH_FIFO_ADDR_MASK GENMASK(9, 0)81#define MCDT_ADC_FIFO_SHIFT 1682#define MCDT_FIFO_LENGTH 51283 84#define MCDT_ADC_CHANNEL_NUM 1085#define MCDT_DAC_CHANNEL_NUM 1086#define MCDT_CHANNEL_NUM (MCDT_ADC_CHANNEL_NUM + MCDT_DAC_CHANNEL_NUM)87 88enum sprd_mcdt_fifo_int {89 MCDT_ADC_FIFO_AE_INT,90 MCDT_ADC_FIFO_AF_INT,91 MCDT_DAC_FIFO_AE_INT,92 MCDT_DAC_FIFO_AF_INT,93 MCDT_ADC_FIFO_OV_INT,94 MCDT_DAC_FIFO_OV_INT95};96 97enum sprd_mcdt_fifo_sts {98 MCDT_ADC_FIFO_REAL_FULL,99 MCDT_ADC_FIFO_REAL_EMPTY,100 MCDT_ADC_FIFO_AF,101 MCDT_ADC_FIFO_AE,102 MCDT_DAC_FIFO_REAL_FULL,103 MCDT_DAC_FIFO_REAL_EMPTY,104 MCDT_DAC_FIFO_AF,105 MCDT_DAC_FIFO_AE106};107 108struct sprd_mcdt_dev {109 struct device *dev;110 void __iomem *base;111 spinlock_t lock;112 struct sprd_mcdt_chan chan[MCDT_CHANNEL_NUM];113};114 115static LIST_HEAD(sprd_mcdt_chan_list);116static DEFINE_MUTEX(sprd_mcdt_list_mutex);117 118static void sprd_mcdt_update(struct sprd_mcdt_dev *mcdt, u32 reg, u32 val,119 u32 mask)120{121 u32 orig = readl_relaxed(mcdt->base + reg);122 u32 tmp;123 124 tmp = (orig & ~mask) | val;125 writel_relaxed(tmp, mcdt->base + reg);126}127 128static void sprd_mcdt_dac_set_watermark(struct sprd_mcdt_dev *mcdt, u8 channel,129 u32 full, u32 empty)130{131 u32 reg = MCDT_DAC0_WTMK + channel * 4;132 u32 water_mark =133 (empty << MCDT_CH_FIFO_AE_SHIFT) & MCDT_CH_FIFO_AE_MASK;134 135 water_mark |= full & MCDT_CH_FIFO_AF_MASK;136 sprd_mcdt_update(mcdt, reg, water_mark,137 MCDT_CH_FIFO_AE_MASK | MCDT_CH_FIFO_AF_MASK);138}139 140static void sprd_mcdt_adc_set_watermark(struct sprd_mcdt_dev *mcdt, u8 channel,141 u32 full, u32 empty)142{143 u32 reg = MCDT_ADC0_WTMK + channel * 4;144 u32 water_mark =145 (empty << MCDT_CH_FIFO_AE_SHIFT) & MCDT_CH_FIFO_AE_MASK;146 147 water_mark |= full & MCDT_CH_FIFO_AF_MASK;148 sprd_mcdt_update(mcdt, reg, water_mark,149 MCDT_CH_FIFO_AE_MASK | MCDT_CH_FIFO_AF_MASK);150}151 152static void sprd_mcdt_dac_dma_enable(struct sprd_mcdt_dev *mcdt, u8 channel,153 bool enable)154{155 u32 shift = MCDT_DAC_DMA_SHIFT + channel;156 157 if (enable)158 sprd_mcdt_update(mcdt, MCDT_DMA_EN, BIT(shift), BIT(shift));159 else160 sprd_mcdt_update(mcdt, MCDT_DMA_EN, 0, BIT(shift));161}162 163static void sprd_mcdt_adc_dma_enable(struct sprd_mcdt_dev *mcdt, u8 channel,164 bool enable)165{166 if (enable)167 sprd_mcdt_update(mcdt, MCDT_DMA_EN, BIT(channel), BIT(channel));168 else169 sprd_mcdt_update(mcdt, MCDT_DMA_EN, 0, BIT(channel));170}171 172static void sprd_mcdt_ap_int_enable(struct sprd_mcdt_dev *mcdt, u8 channel,173 bool enable)174{175 if (enable)176 sprd_mcdt_update(mcdt, MCDT_INT_MSK_CFG0, BIT(channel),177 BIT(channel));178 else179 sprd_mcdt_update(mcdt, MCDT_INT_MSK_CFG0, 0, BIT(channel));180}181 182static void sprd_mcdt_dac_write_fifo(struct sprd_mcdt_dev *mcdt, u8 channel,183 u32 val)184{185 u32 reg = MCDT_CH0_TXD + channel * 4;186 187 writel_relaxed(val, mcdt->base + reg);188}189 190static void sprd_mcdt_adc_read_fifo(struct sprd_mcdt_dev *mcdt, u8 channel,191 u32 *val)192{193 u32 reg = MCDT_CH0_RXD + channel * 4;194 195 *val = readl_relaxed(mcdt->base + reg);196}197 198static void sprd_mcdt_dac_dma_chn_select(struct sprd_mcdt_dev *mcdt, u8 channel,199 enum sprd_mcdt_dma_chan dma_chan)200{201 switch (dma_chan) {202 case SPRD_MCDT_DMA_CH0:203 sprd_mcdt_update(mcdt, MCDT_DMA_CFG0,204 channel << MCDT_DMA_CH0_SEL_SHIFT,205 MCDT_DMA_CH0_SEL_MASK);206 break;207 208 case SPRD_MCDT_DMA_CH1:209 sprd_mcdt_update(mcdt, MCDT_DMA_CFG0,210 channel << MCDT_DMA_CH1_SEL_SHIFT,211 MCDT_DMA_CH1_SEL_MASK);212 break;213 214 case SPRD_MCDT_DMA_CH2:215 sprd_mcdt_update(mcdt, MCDT_DMA_CFG0,216 channel << MCDT_DMA_CH2_SEL_SHIFT,217 MCDT_DMA_CH2_SEL_MASK);218 break;219 220 case SPRD_MCDT_DMA_CH3:221 sprd_mcdt_update(mcdt, MCDT_DMA_CFG0,222 channel << MCDT_DMA_CH3_SEL_SHIFT,223 MCDT_DMA_CH3_SEL_MASK);224 break;225 226 case SPRD_MCDT_DMA_CH4:227 sprd_mcdt_update(mcdt, MCDT_DMA_CFG0,228 channel << MCDT_DMA_CH4_SEL_SHIFT,229 MCDT_DMA_CH4_SEL_MASK);230 break;231 }232}233 234static void sprd_mcdt_adc_dma_chn_select(struct sprd_mcdt_dev *mcdt, u8 channel,235 enum sprd_mcdt_dma_chan dma_chan)236{237 switch (dma_chan) {238 case SPRD_MCDT_DMA_CH0:239 sprd_mcdt_update(mcdt, MCDT_DMA_CFG1,240 channel << MCDT_DMA_CH0_SEL_SHIFT,241 MCDT_DMA_CH0_SEL_MASK);242 break;243 244 case SPRD_MCDT_DMA_CH1:245 sprd_mcdt_update(mcdt, MCDT_DMA_CFG1,246 channel << MCDT_DMA_CH1_SEL_SHIFT,247 MCDT_DMA_CH1_SEL_MASK);248 break;249 250 case SPRD_MCDT_DMA_CH2:251 sprd_mcdt_update(mcdt, MCDT_DMA_CFG1,252 channel << MCDT_DMA_CH2_SEL_SHIFT,253 MCDT_DMA_CH2_SEL_MASK);254 break;255 256 case SPRD_MCDT_DMA_CH3:257 sprd_mcdt_update(mcdt, MCDT_DMA_CFG1,258 channel << MCDT_DMA_CH3_SEL_SHIFT,259 MCDT_DMA_CH3_SEL_MASK);260 break;261 262 case SPRD_MCDT_DMA_CH4:263 sprd_mcdt_update(mcdt, MCDT_DMA_CFG1,264 channel << MCDT_DMA_CH4_SEL_SHIFT,265 MCDT_DMA_CH4_SEL_MASK);266 break;267 }268}269 270static u32 sprd_mcdt_dma_ack_shift(u8 channel)271{272 switch (channel) {273 default:274 case 0:275 case 8:276 return 0;277 case 1:278 case 9:279 return 4;280 case 2:281 return 8;282 case 3:283 return 12;284 case 4:285 return 16;286 case 5:287 return 20;288 case 6:289 return 24;290 case 7:291 return 28;292 }293}294 295static void sprd_mcdt_dac_dma_ack_select(struct sprd_mcdt_dev *mcdt, u8 channel,296 enum sprd_mcdt_dma_chan dma_chan)297{298 u32 reg, shift = sprd_mcdt_dma_ack_shift(channel), ack = dma_chan;299 300 switch (channel) {301 case 0 ... 7:302 reg = MCDT_DMA_CFG2;303 break;304 305 case 8 ... 9:306 reg = MCDT_DMA_CFG3;307 break;308 309 default:310 return;311 }312 313 sprd_mcdt_update(mcdt, reg, ack << shift,314 MCDT_DMA_ACK_SEL_MASK << shift);315}316 317static void sprd_mcdt_adc_dma_ack_select(struct sprd_mcdt_dev *mcdt, u8 channel,318 enum sprd_mcdt_dma_chan dma_chan)319{320 u32 reg, shift = sprd_mcdt_dma_ack_shift(channel), ack = dma_chan;321 322 switch (channel) {323 case 0 ... 7:324 reg = MCDT_DMA_CFG4;325 break;326 327 case 8 ... 9:328 reg = MCDT_DMA_CFG5;329 break;330 331 default:332 return;333 }334 335 sprd_mcdt_update(mcdt, reg, ack << shift,336 MCDT_DMA_ACK_SEL_MASK << shift);337}338 339static bool sprd_mcdt_chan_fifo_sts(struct sprd_mcdt_dev *mcdt, u8 channel,340 enum sprd_mcdt_fifo_sts fifo_sts)341{342 u32 reg, shift;343 344 switch (channel) {345 case 0 ... 3:346 reg = MCDT_CH_FIFO_ST0;347 break;348 case 4 ... 7:349 reg = MCDT_CH_FIFO_ST1;350 break;351 case 8 ... 9:352 reg = MCDT_CH_FIFO_ST2;353 break;354 default:355 return false;356 }357 358 switch (channel) {359 case 0:360 case 4:361 case 8:362 shift = fifo_sts;363 break;364 365 case 1:366 case 5:367 case 9:368 shift = 8 + fifo_sts;369 break;370 371 case 2:372 case 6:373 shift = 16 + fifo_sts;374 break;375 376 case 3:377 case 7:378 shift = 24 + fifo_sts;379 break;380 381 default:382 return false;383 }384 385 return !!(readl_relaxed(mcdt->base + reg) & BIT(shift));386}387 388static void sprd_mcdt_dac_fifo_clear(struct sprd_mcdt_dev *mcdt, u8 channel)389{390 sprd_mcdt_update(mcdt, MCDT_FIFO_CLR, BIT(channel), BIT(channel));391}392 393static void sprd_mcdt_adc_fifo_clear(struct sprd_mcdt_dev *mcdt, u8 channel)394{395 u32 shift = MCDT_ADC_FIFO_SHIFT + channel;396 397 sprd_mcdt_update(mcdt, MCDT_FIFO_CLR, BIT(shift), BIT(shift));398}399 400static u32 sprd_mcdt_dac_fifo_avail(struct sprd_mcdt_dev *mcdt, u8 channel)401{402 u32 reg = MCDT_DAC0_FIFO_ADDR_ST + channel * 8;403 u32 r_addr = (readl_relaxed(mcdt->base + reg) >>404 MCDT_CH_FIFO_ADDR_SHIFT) & MCDT_CH_FIFO_ADDR_MASK;405 u32 w_addr = readl_relaxed(mcdt->base + reg) & MCDT_CH_FIFO_ADDR_MASK;406 407 if (w_addr >= r_addr)408 return 4 * (MCDT_FIFO_LENGTH - w_addr + r_addr);409 else410 return 4 * (r_addr - w_addr);411}412 413static u32 sprd_mcdt_adc_fifo_avail(struct sprd_mcdt_dev *mcdt, u8 channel)414{415 u32 reg = MCDT_ADC0_FIFO_ADDR_ST + channel * 8;416 u32 r_addr = (readl_relaxed(mcdt->base + reg) >>417 MCDT_CH_FIFO_ADDR_SHIFT) & MCDT_CH_FIFO_ADDR_MASK;418 u32 w_addr = readl_relaxed(mcdt->base + reg) & MCDT_CH_FIFO_ADDR_MASK;419 420 if (w_addr >= r_addr)421 return 4 * (w_addr - r_addr);422 else423 return 4 * (MCDT_FIFO_LENGTH - r_addr + w_addr);424}425 426static u32 sprd_mcdt_int_type_shift(u8 channel,427 enum sprd_mcdt_fifo_int int_type)428{429 switch (channel) {430 case 0:431 case 4:432 case 8:433 return int_type;434 435 case 1:436 case 5:437 case 9:438 return 8 + int_type;439 440 case 2:441 case 6:442 return 16 + int_type;443 444 case 3:445 case 7:446 return 24 + int_type;447 448 default:449 return 0;450 }451}452 453static void sprd_mcdt_chan_int_en(struct sprd_mcdt_dev *mcdt, u8 channel,454 enum sprd_mcdt_fifo_int int_type, bool enable)455{456 u32 reg, shift = sprd_mcdt_int_type_shift(channel, int_type);457 458 switch (channel) {459 case 0 ... 3:460 reg = MCDT_INT_EN0;461 break;462 case 4 ... 7:463 reg = MCDT_INT_EN1;464 break;465 case 8 ... 9:466 reg = MCDT_INT_EN2;467 break;468 default:469 return;470 }471 472 if (enable)473 sprd_mcdt_update(mcdt, reg, BIT(shift), BIT(shift));474 else475 sprd_mcdt_update(mcdt, reg, 0, BIT(shift));476}477 478static void sprd_mcdt_chan_int_clear(struct sprd_mcdt_dev *mcdt, u8 channel,479 enum sprd_mcdt_fifo_int int_type)480{481 u32 reg, shift = sprd_mcdt_int_type_shift(channel, int_type);482 483 switch (channel) {484 case 0 ... 3:485 reg = MCDT_INT_CLR0;486 break;487 case 4 ... 7:488 reg = MCDT_INT_CLR1;489 break;490 case 8 ... 9:491 reg = MCDT_INT_CLR2;492 break;493 default:494 return;495 }496 497 sprd_mcdt_update(mcdt, reg, BIT(shift), BIT(shift));498}499 500static bool sprd_mcdt_chan_int_sts(struct sprd_mcdt_dev *mcdt, u8 channel,501 enum sprd_mcdt_fifo_int int_type)502{503 u32 reg, shift = sprd_mcdt_int_type_shift(channel, int_type);504 505 switch (channel) {506 case 0 ... 3:507 reg = MCDT_INT_MSK1;508 break;509 case 4 ... 7:510 reg = MCDT_INT_MSK2;511 break;512 case 8 ... 9:513 reg = MCDT_INT_MSK3;514 break;515 default:516 return false;517 }518 519 return !!(readl_relaxed(mcdt->base + reg) & BIT(shift));520}521 522static irqreturn_t sprd_mcdt_irq_handler(int irq, void *dev_id)523{524 struct sprd_mcdt_dev *mcdt = (struct sprd_mcdt_dev *)dev_id;525 int i;526 527 spin_lock(&mcdt->lock);528 529 for (i = 0; i < MCDT_ADC_CHANNEL_NUM; i++) {530 if (sprd_mcdt_chan_int_sts(mcdt, i, MCDT_ADC_FIFO_AF_INT)) {531 struct sprd_mcdt_chan *chan = &mcdt->chan[i];532 533 sprd_mcdt_chan_int_clear(mcdt, i, MCDT_ADC_FIFO_AF_INT);534 if (chan->cb)535 chan->cb->notify(chan->cb->data);536 }537 }538 539 for (i = 0; i < MCDT_DAC_CHANNEL_NUM; i++) {540 if (sprd_mcdt_chan_int_sts(mcdt, i, MCDT_DAC_FIFO_AE_INT)) {541 struct sprd_mcdt_chan *chan =542 &mcdt->chan[i + MCDT_ADC_CHANNEL_NUM];543 544 sprd_mcdt_chan_int_clear(mcdt, i, MCDT_DAC_FIFO_AE_INT);545 if (chan->cb)546 chan->cb->notify(chan->cb->data);547 }548 }549 550 spin_unlock(&mcdt->lock);551 552 return IRQ_HANDLED;553}554 555/**556 * sprd_mcdt_chan_write - write data to the MCDT channel's fifo557 * @chan: the MCDT channel558 * @tx_buf: send buffer559 * @size: data size560 *561 * Note: We can not write data to the channel fifo when enabling the DMA mode,562 * otherwise the channel fifo data will be invalid.563 *564 * If there are not enough space of the channel fifo, it will return errors565 * to users.566 *567 * Returns 0 on success, or an appropriate error code on failure.568 */569int sprd_mcdt_chan_write(struct sprd_mcdt_chan *chan, char *tx_buf, u32 size)570{571 struct sprd_mcdt_dev *mcdt = chan->mcdt;572 unsigned long flags;573 int avail, i = 0, words = size / 4;574 u32 *buf = (u32 *)tx_buf;575 576 spin_lock_irqsave(&mcdt->lock, flags);577 578 if (chan->dma_enable) {579 dev_err(mcdt->dev,580 "Can not write data when DMA mode enabled\n");581 spin_unlock_irqrestore(&mcdt->lock, flags);582 return -EINVAL;583 }584 585 if (sprd_mcdt_chan_fifo_sts(mcdt, chan->id, MCDT_DAC_FIFO_REAL_FULL)) {586 dev_err(mcdt->dev, "Channel fifo is full now\n");587 spin_unlock_irqrestore(&mcdt->lock, flags);588 return -EBUSY;589 }590 591 avail = sprd_mcdt_dac_fifo_avail(mcdt, chan->id);592 if (size > avail) {593 dev_err(mcdt->dev,594 "Data size is larger than the available fifo size\n");595 spin_unlock_irqrestore(&mcdt->lock, flags);596 return -EBUSY;597 }598 599 while (i++ < words)600 sprd_mcdt_dac_write_fifo(mcdt, chan->id, *buf++);601 602 spin_unlock_irqrestore(&mcdt->lock, flags);603 return 0;604}605EXPORT_SYMBOL_GPL(sprd_mcdt_chan_write);606 607/**608 * sprd_mcdt_chan_read - read data from the MCDT channel's fifo609 * @chan: the MCDT channel610 * @rx_buf: receive buffer611 * @size: data size612 *613 * Note: We can not read data from the channel fifo when enabling the DMA mode,614 * otherwise the reading data will be invalid.615 *616 * Usually user need start to read data once receiving the fifo full interrupt.617 *618 * Returns data size of reading successfully, or an error code on failure.619 */620int sprd_mcdt_chan_read(struct sprd_mcdt_chan *chan, char *rx_buf, u32 size)621{622 struct sprd_mcdt_dev *mcdt = chan->mcdt;623 unsigned long flags;624 int i = 0, avail, words = size / 4;625 u32 *buf = (u32 *)rx_buf;626 627 spin_lock_irqsave(&mcdt->lock, flags);628 629 if (chan->dma_enable) {630 dev_err(mcdt->dev, "Can not read data when DMA mode enabled\n");631 spin_unlock_irqrestore(&mcdt->lock, flags);632 return -EINVAL;633 }634 635 if (sprd_mcdt_chan_fifo_sts(mcdt, chan->id, MCDT_ADC_FIFO_REAL_EMPTY)) {636 dev_err(mcdt->dev, "Channel fifo is empty\n");637 spin_unlock_irqrestore(&mcdt->lock, flags);638 return -EBUSY;639 }640 641 avail = sprd_mcdt_adc_fifo_avail(mcdt, chan->id);642 if (size > avail)643 words = avail / 4;644 645 while (i++ < words)646 sprd_mcdt_adc_read_fifo(mcdt, chan->id, buf++);647 648 spin_unlock_irqrestore(&mcdt->lock, flags);649 return words * 4;650}651EXPORT_SYMBOL_GPL(sprd_mcdt_chan_read);652 653/**654 * sprd_mcdt_chan_int_enable - enable the interrupt mode for the MCDT channel655 * @chan: the MCDT channel656 * @water_mark: water mark to trigger a interrupt657 * @cb: callback when a interrupt happened658 *659 * Now it only can enable fifo almost full interrupt for ADC channel and fifo660 * almost empty interrupt for DAC channel. Morevoer for interrupt mode, user661 * should use sprd_mcdt_chan_read() or sprd_mcdt_chan_write() to read or write662 * data manually.663 *664 * For ADC channel, user can start to read data once receiving one fifo full665 * interrupt. For DAC channel, user can start to write data once receiving one666 * fifo empty interrupt or just call sprd_mcdt_chan_write() to write data667 * directly.668 *669 * Returns 0 on success, or an error code on failure.670 */671int sprd_mcdt_chan_int_enable(struct sprd_mcdt_chan *chan, u32 water_mark,672 struct sprd_mcdt_chan_callback *cb)673{674 struct sprd_mcdt_dev *mcdt = chan->mcdt;675 unsigned long flags;676 int ret = 0;677 678 spin_lock_irqsave(&mcdt->lock, flags);679 680 if (chan->dma_enable || chan->int_enable) {681 dev_err(mcdt->dev, "Failed to set interrupt mode.\n");682 spin_unlock_irqrestore(&mcdt->lock, flags);683 return -EINVAL;684 }685 686 switch (chan->type) {687 case SPRD_MCDT_ADC_CHAN:688 sprd_mcdt_adc_fifo_clear(mcdt, chan->id);689 sprd_mcdt_adc_set_watermark(mcdt, chan->id, water_mark,690 MCDT_FIFO_LENGTH - 1);691 sprd_mcdt_chan_int_en(mcdt, chan->id,692 MCDT_ADC_FIFO_AF_INT, true);693 sprd_mcdt_ap_int_enable(mcdt, chan->id, true);694 break;695 696 case SPRD_MCDT_DAC_CHAN:697 sprd_mcdt_dac_fifo_clear(mcdt, chan->id);698 sprd_mcdt_dac_set_watermark(mcdt, chan->id,699 MCDT_FIFO_LENGTH - 1, water_mark);700 sprd_mcdt_chan_int_en(mcdt, chan->id,701 MCDT_DAC_FIFO_AE_INT, true);702 sprd_mcdt_ap_int_enable(mcdt, chan->id, true);703 break;704 705 default:706 dev_err(mcdt->dev, "Unsupported channel type\n");707 ret = -EINVAL;708 }709 710 if (!ret) {711 chan->cb = cb;712 chan->int_enable = true;713 }714 715 spin_unlock_irqrestore(&mcdt->lock, flags);716 717 return ret;718}719EXPORT_SYMBOL_GPL(sprd_mcdt_chan_int_enable);720 721/**722 * sprd_mcdt_chan_int_disable - disable the interrupt mode for the MCDT channel723 * @chan: the MCDT channel724 */725void sprd_mcdt_chan_int_disable(struct sprd_mcdt_chan *chan)726{727 struct sprd_mcdt_dev *mcdt = chan->mcdt;728 unsigned long flags;729 730 spin_lock_irqsave(&mcdt->lock, flags);731 732 if (!chan->int_enable) {733 spin_unlock_irqrestore(&mcdt->lock, flags);734 return;735 }736 737 switch (chan->type) {738 case SPRD_MCDT_ADC_CHAN:739 sprd_mcdt_chan_int_en(mcdt, chan->id,740 MCDT_ADC_FIFO_AF_INT, false);741 sprd_mcdt_chan_int_clear(mcdt, chan->id, MCDT_ADC_FIFO_AF_INT);742 sprd_mcdt_ap_int_enable(mcdt, chan->id, false);743 break;744 745 case SPRD_MCDT_DAC_CHAN:746 sprd_mcdt_chan_int_en(mcdt, chan->id,747 MCDT_DAC_FIFO_AE_INT, false);748 sprd_mcdt_chan_int_clear(mcdt, chan->id, MCDT_DAC_FIFO_AE_INT);749 sprd_mcdt_ap_int_enable(mcdt, chan->id, false);750 break;751 752 default:753 break;754 }755 756 chan->int_enable = false;757 spin_unlock_irqrestore(&mcdt->lock, flags);758}759EXPORT_SYMBOL_GPL(sprd_mcdt_chan_int_disable);760 761/**762 * sprd_mcdt_chan_dma_enable - enable the DMA mode for the MCDT channel763 * @chan: the MCDT channel764 * @dma_chan: specify which DMA channel will be used for this MCDT channel765 * @water_mark: water mark to trigger a DMA request766 *767 * Enable the DMA mode for the MCDT channel, that means we can use DMA to768 * transfer data to the channel fifo and do not need reading/writing data769 * manually.770 *771 * Returns 0 on success, or an error code on failure.772 */773int sprd_mcdt_chan_dma_enable(struct sprd_mcdt_chan *chan,774 enum sprd_mcdt_dma_chan dma_chan,775 u32 water_mark)776{777 struct sprd_mcdt_dev *mcdt = chan->mcdt;778 unsigned long flags;779 int ret = 0;780 781 spin_lock_irqsave(&mcdt->lock, flags);782 783 if (chan->dma_enable || chan->int_enable ||784 dma_chan > SPRD_MCDT_DMA_CH4) {785 dev_err(mcdt->dev, "Failed to set DMA mode\n");786 spin_unlock_irqrestore(&mcdt->lock, flags);787 return -EINVAL;788 }789 790 switch (chan->type) {791 case SPRD_MCDT_ADC_CHAN:792 sprd_mcdt_adc_fifo_clear(mcdt, chan->id);793 sprd_mcdt_adc_set_watermark(mcdt, chan->id,794 water_mark, MCDT_FIFO_LENGTH - 1);795 sprd_mcdt_adc_dma_enable(mcdt, chan->id, true);796 sprd_mcdt_adc_dma_chn_select(mcdt, chan->id, dma_chan);797 sprd_mcdt_adc_dma_ack_select(mcdt, chan->id, dma_chan);798 break;799 800 case SPRD_MCDT_DAC_CHAN:801 sprd_mcdt_dac_fifo_clear(mcdt, chan->id);802 sprd_mcdt_dac_set_watermark(mcdt, chan->id,803 MCDT_FIFO_LENGTH - 1, water_mark);804 sprd_mcdt_dac_dma_enable(mcdt, chan->id, true);805 sprd_mcdt_dac_dma_chn_select(mcdt, chan->id, dma_chan);806 sprd_mcdt_dac_dma_ack_select(mcdt, chan->id, dma_chan);807 break;808 809 default:810 dev_err(mcdt->dev, "Unsupported channel type\n");811 ret = -EINVAL;812 }813 814 if (!ret)815 chan->dma_enable = true;816 817 spin_unlock_irqrestore(&mcdt->lock, flags);818 819 return ret;820}821EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_enable);822 823/**824 * sprd_mcdt_chan_dma_disable - disable the DMA mode for the MCDT channel825 * @chan: the MCDT channel826 */827void sprd_mcdt_chan_dma_disable(struct sprd_mcdt_chan *chan)828{829 struct sprd_mcdt_dev *mcdt = chan->mcdt;830 unsigned long flags;831 832 spin_lock_irqsave(&mcdt->lock, flags);833 834 if (!chan->dma_enable) {835 spin_unlock_irqrestore(&mcdt->lock, flags);836 return;837 }838 839 switch (chan->type) {840 case SPRD_MCDT_ADC_CHAN:841 sprd_mcdt_adc_dma_enable(mcdt, chan->id, false);842 sprd_mcdt_adc_fifo_clear(mcdt, chan->id);843 break;844 845 case SPRD_MCDT_DAC_CHAN:846 sprd_mcdt_dac_dma_enable(mcdt, chan->id, false);847 sprd_mcdt_dac_fifo_clear(mcdt, chan->id);848 break;849 850 default:851 break;852 }853 854 chan->dma_enable = false;855 spin_unlock_irqrestore(&mcdt->lock, flags);856}857EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_disable);858 859/**860 * sprd_mcdt_request_chan - request one MCDT channel861 * @channel: channel id862 * @type: channel type, it can be one ADC channel or DAC channel863 *864 * Rreturn NULL if no available channel.865 */866struct sprd_mcdt_chan *sprd_mcdt_request_chan(u8 channel,867 enum sprd_mcdt_channel_type type)868{869 struct sprd_mcdt_chan *temp;870 871 mutex_lock(&sprd_mcdt_list_mutex);872 873 list_for_each_entry(temp, &sprd_mcdt_chan_list, list) {874 if (temp->type == type && temp->id == channel) {875 list_del_init(&temp->list);876 break;877 }878 }879 880 if (list_entry_is_head(temp, &sprd_mcdt_chan_list, list))881 temp = NULL;882 883 mutex_unlock(&sprd_mcdt_list_mutex);884 885 return temp;886}887EXPORT_SYMBOL_GPL(sprd_mcdt_request_chan);888 889/**890 * sprd_mcdt_free_chan - free one MCDT channel891 * @chan: the channel to be freed892 */893void sprd_mcdt_free_chan(struct sprd_mcdt_chan *chan)894{895 struct sprd_mcdt_chan *temp;896 897 sprd_mcdt_chan_dma_disable(chan);898 sprd_mcdt_chan_int_disable(chan);899 900 mutex_lock(&sprd_mcdt_list_mutex);901 902 list_for_each_entry(temp, &sprd_mcdt_chan_list, list) {903 if (temp == chan) {904 mutex_unlock(&sprd_mcdt_list_mutex);905 return;906 }907 }908 909 list_add_tail(&chan->list, &sprd_mcdt_chan_list);910 mutex_unlock(&sprd_mcdt_list_mutex);911}912EXPORT_SYMBOL_GPL(sprd_mcdt_free_chan);913 914static void sprd_mcdt_init_chans(struct sprd_mcdt_dev *mcdt,915 struct resource *res)916{917 int i;918 919 for (i = 0; i < MCDT_CHANNEL_NUM; i++) {920 struct sprd_mcdt_chan *chan = &mcdt->chan[i];921 922 if (i < MCDT_ADC_CHANNEL_NUM) {923 chan->id = i;924 chan->type = SPRD_MCDT_ADC_CHAN;925 chan->fifo_phys = res->start + MCDT_CH0_RXD + i * 4;926 } else {927 chan->id = i - MCDT_ADC_CHANNEL_NUM;928 chan->type = SPRD_MCDT_DAC_CHAN;929 chan->fifo_phys = res->start + MCDT_CH0_TXD +930 (i - MCDT_ADC_CHANNEL_NUM) * 4;931 }932 933 chan->mcdt = mcdt;934 INIT_LIST_HEAD(&chan->list);935 936 mutex_lock(&sprd_mcdt_list_mutex);937 list_add_tail(&chan->list, &sprd_mcdt_chan_list);938 mutex_unlock(&sprd_mcdt_list_mutex);939 }940}941 942static int sprd_mcdt_probe(struct platform_device *pdev)943{944 struct sprd_mcdt_dev *mcdt;945 struct resource *res;946 int ret, irq;947 948 mcdt = devm_kzalloc(&pdev->dev, sizeof(*mcdt), GFP_KERNEL);949 if (!mcdt)950 return -ENOMEM;951 952 mcdt->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);953 if (IS_ERR(mcdt->base))954 return PTR_ERR(mcdt->base);955 956 mcdt->dev = &pdev->dev;957 spin_lock_init(&mcdt->lock);958 platform_set_drvdata(pdev, mcdt);959 960 irq = platform_get_irq(pdev, 0);961 if (irq < 0)962 return irq;963 964 ret = devm_request_irq(&pdev->dev, irq, sprd_mcdt_irq_handler,965 0, "sprd-mcdt", mcdt);966 if (ret) {967 dev_err(&pdev->dev, "Failed to request MCDT IRQ\n");968 return ret;969 }970 971 sprd_mcdt_init_chans(mcdt, res);972 973 return 0;974}975 976static void sprd_mcdt_remove(struct platform_device *pdev)977{978 struct sprd_mcdt_chan *chan, *temp;979 980 mutex_lock(&sprd_mcdt_list_mutex);981 982 list_for_each_entry_safe(chan, temp, &sprd_mcdt_chan_list, list)983 list_del(&chan->list);984 985 mutex_unlock(&sprd_mcdt_list_mutex);986}987 988static const struct of_device_id sprd_mcdt_of_match[] = {989 { .compatible = "sprd,sc9860-mcdt", },990 { }991};992MODULE_DEVICE_TABLE(of, sprd_mcdt_of_match);993 994static struct platform_driver sprd_mcdt_driver = {995 .probe = sprd_mcdt_probe,996 .remove = sprd_mcdt_remove,997 .driver = {998 .name = "sprd-mcdt",999 .of_match_table = sprd_mcdt_of_match,1000 },1001};1002 1003module_platform_driver(sprd_mcdt_driver);1004 1005MODULE_DESCRIPTION("Spreadtrum Multi-Channel Data Transfer Driver");1006MODULE_LICENSE("GPL v2");1007