1239281Sgonzo/*- 2239281Sgonzo * Copyright (c) 2011 3239281Sgonzo * Ben Gray <ben.r.gray@gmail.com>. 4239281Sgonzo * All rights reserved. 5239281Sgonzo * 6239281Sgonzo * Redistribution and use in source and binary forms, with or without 7239281Sgonzo * modification, are permitted provided that the following conditions 8239281Sgonzo * are met: 9239281Sgonzo * 1. Redistributions of source code must retain the above copyright 10239281Sgonzo * notice, this list of conditions and the following disclaimer. 11239281Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 12239281Sgonzo * notice, this list of conditions and the following disclaimer in the 13239281Sgonzo * documentation and/or other materials provided with the distribution. 14239281Sgonzo * 15239281Sgonzo * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16239281Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17239281Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18239281Sgonzo * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 19239281Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20239281Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21239281Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22239281Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23239281Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24239281Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25239281Sgonzo * SUCH DAMAGE. 26239281Sgonzo */ 27239281Sgonzo 28239281Sgonzo#include <sys/cdefs.h> 29239281Sgonzo__FBSDID("$FreeBSD: releng/10.3/sys/arm/ti/ti_sdma.c 266152 2014-05-15 16:11:06Z ian $"); 30239281Sgonzo 31239281Sgonzo#include <sys/param.h> 32239281Sgonzo#include <sys/systm.h> 33239281Sgonzo#include <sys/bus.h> 34239281Sgonzo#include <sys/kernel.h> 35239281Sgonzo#include <sys/lock.h> 36239281Sgonzo#include <sys/interrupt.h> 37239281Sgonzo#include <sys/module.h> 38239281Sgonzo#include <sys/malloc.h> 39239281Sgonzo#include <sys/mutex.h> 40239281Sgonzo#include <sys/rman.h> 41239281Sgonzo#include <sys/queue.h> 42239281Sgonzo#include <sys/taskqueue.h> 43239281Sgonzo#include <sys/timetc.h> 44239281Sgonzo#include <machine/bus.h> 45239281Sgonzo#include <machine/intr.h> 46239281Sgonzo 47239281Sgonzo#include <dev/fdt/fdt_common.h> 48239281Sgonzo#include <dev/ofw/openfirm.h> 49239281Sgonzo#include <dev/ofw/ofw_bus.h> 50239281Sgonzo#include <dev/ofw/ofw_bus_subr.h> 51239281Sgonzo 52239281Sgonzo#include <arm/ti/ti_cpuid.h> 53239281Sgonzo#include <arm/ti/ti_prcm.h> 54239281Sgonzo#include <arm/ti/ti_sdma.h> 55239281Sgonzo#include <arm/ti/ti_sdmareg.h> 56239281Sgonzo 57239281Sgonzo/** 58239281Sgonzo * Kernel functions for using the DMA controller 59239281Sgonzo * 60239281Sgonzo * 61239281Sgonzo * DMA TRANSFERS: 62239281Sgonzo * A DMA transfer block consists of a number of frames (FN). Each frame 63239281Sgonzo * consists of a number of elements, and each element can have a size of 8, 16, 64239281Sgonzo * or 32 bits. 65239281Sgonzo * 66239281Sgonzo * OMAP44xx and newer chips support linked list (aka scatter gather) transfers, 67239281Sgonzo * where a linked list of source/destination pairs can be placed in memory 68239281Sgonzo * for the H/W to process. Earlier chips only allowed you to chain multiple 69239281Sgonzo * channels together. However currently this linked list feature is not 70239281Sgonzo * supported by the driver. 71239281Sgonzo * 72239281Sgonzo */ 73239281Sgonzo 74239281Sgonzo/** 75239281Sgonzo * Data structure per DMA channel. 76239281Sgonzo * 77239281Sgonzo * 78239281Sgonzo */ 79239281Sgonzostruct ti_sdma_channel { 80239281Sgonzo 81239281Sgonzo /* 82239281Sgonzo * The configuration registers for the given channel, these are modified 83239281Sgonzo * by the set functions and only written to the actual registers when a 84239281Sgonzo * transaction is started. 85239281Sgonzo */ 86239281Sgonzo uint32_t reg_csdp; 87239281Sgonzo uint32_t reg_ccr; 88239281Sgonzo uint32_t reg_cicr; 89239281Sgonzo 90239281Sgonzo /* Set when one of the configuration registers above change */ 91239281Sgonzo uint32_t need_reg_write; 92239281Sgonzo 93239281Sgonzo /* Callback function used when an interrupt is tripped on the given channel */ 94239281Sgonzo void (*callback)(unsigned int ch, uint32_t ch_status, void *data); 95239281Sgonzo 96239281Sgonzo /* Callback data passed in the callback ... duh */ 97239281Sgonzo void* callback_data; 98239281Sgonzo 99239281Sgonzo}; 100239281Sgonzo 101239281Sgonzo/** 102239281Sgonzo * DMA driver context, allocated and stored globally, this driver is not 103239281Sgonzo * intetned to ever be unloaded (see ti_sdma_sc). 104239281Sgonzo * 105239281Sgonzo */ 106239281Sgonzostruct ti_sdma_softc { 107239281Sgonzo device_t sc_dev; 108239281Sgonzo struct resource* sc_irq_res; 109239281Sgonzo struct resource* sc_mem_res; 110239281Sgonzo 111239281Sgonzo /* 112239281Sgonzo * I guess in theory we should have a mutex per DMA channel for register 113239281Sgonzo * modifications. But since we know we are never going to be run on a SMP 114239281Sgonzo * system, we can use just the single lock for all channels. 115239281Sgonzo */ 116239281Sgonzo struct mtx sc_mtx; 117239281Sgonzo 118239281Sgonzo /* Stores the H/W revision read from the registers */ 119239281Sgonzo uint32_t sc_hw_rev; 120239281Sgonzo 121239281Sgonzo /* 122239281Sgonzo * Bits in the sc_active_channels data field indicate if the channel has 123239281Sgonzo * been activated. 124239281Sgonzo */ 125239281Sgonzo uint32_t sc_active_channels; 126239281Sgonzo 127239281Sgonzo struct ti_sdma_channel sc_channel[NUM_DMA_CHANNELS]; 128239281Sgonzo 129239281Sgonzo}; 130239281Sgonzo 131239281Sgonzostatic struct ti_sdma_softc *ti_sdma_sc = NULL; 132239281Sgonzo 133239281Sgonzo/** 134239281Sgonzo * Macros for driver mutex locking 135239281Sgonzo */ 136239281Sgonzo#define TI_SDMA_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx) 137239281Sgonzo#define TI_SDMA_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx) 138239281Sgonzo#define TI_SDMA_LOCK_INIT(_sc) \ 139239281Sgonzo mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \ 140239281Sgonzo "ti_sdma", MTX_SPIN) 141239281Sgonzo#define TI_SDMA_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); 142239281Sgonzo#define TI_SDMA_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); 143239281Sgonzo#define TI_SDMA_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); 144239281Sgonzo 145239281Sgonzo/** 146239281Sgonzo * Function prototypes 147239281Sgonzo * 148239281Sgonzo */ 149239281Sgonzostatic void ti_sdma_intr(void *); 150239281Sgonzo 151239281Sgonzo/** 152239281Sgonzo * ti_sdma_read_4 - reads a 32-bit value from one of the DMA registers 153239281Sgonzo * @sc: DMA device context 154239281Sgonzo * @off: The offset of a register from the DMA register address range 155239281Sgonzo * 156239281Sgonzo * 157239281Sgonzo * RETURNS: 158239281Sgonzo * 32-bit value read from the register. 159239281Sgonzo */ 160239281Sgonzostatic inline uint32_t 161239281Sgonzoti_sdma_read_4(struct ti_sdma_softc *sc, bus_size_t off) 162239281Sgonzo{ 163239281Sgonzo return bus_read_4(sc->sc_mem_res, off); 164239281Sgonzo} 165239281Sgonzo 166239281Sgonzo/** 167239281Sgonzo * ti_sdma_write_4 - writes a 32-bit value to one of the DMA registers 168239281Sgonzo * @sc: DMA device context 169239281Sgonzo * @off: The offset of a register from the DMA register address range 170239281Sgonzo * 171239281Sgonzo * 172239281Sgonzo * RETURNS: 173239281Sgonzo * 32-bit value read from the register. 174239281Sgonzo */ 175239281Sgonzostatic inline void 176239281Sgonzoti_sdma_write_4(struct ti_sdma_softc *sc, bus_size_t off, uint32_t val) 177239281Sgonzo{ 178239281Sgonzo bus_write_4(sc->sc_mem_res, off, val); 179239281Sgonzo} 180239281Sgonzo 181239281Sgonzo/** 182239281Sgonzo * ti_sdma_is_omap3_rev - returns true if H/W is from OMAP3 series 183239281Sgonzo * @sc: DMA device context 184239281Sgonzo * 185239281Sgonzo */ 186239281Sgonzostatic inline int 187239281Sgonzoti_sdma_is_omap3_rev(struct ti_sdma_softc *sc) 188239281Sgonzo{ 189239281Sgonzo return (sc->sc_hw_rev == DMA4_OMAP3_REV); 190239281Sgonzo} 191239281Sgonzo 192239281Sgonzo/** 193239281Sgonzo * ti_sdma_is_omap4_rev - returns true if H/W is from OMAP4 series 194239281Sgonzo * @sc: DMA device context 195239281Sgonzo * 196239281Sgonzo */ 197239281Sgonzostatic inline int 198239281Sgonzoti_sdma_is_omap4_rev(struct ti_sdma_softc *sc) 199239281Sgonzo{ 200239281Sgonzo return (sc->sc_hw_rev == DMA4_OMAP4_REV); 201239281Sgonzo} 202239281Sgonzo 203239281Sgonzo/** 204239281Sgonzo * ti_sdma_intr - interrupt handler for all 4 DMA IRQs 205239281Sgonzo * @arg: ignored 206239281Sgonzo * 207239281Sgonzo * Called when any of the four DMA IRQs are triggered. 208239281Sgonzo * 209239281Sgonzo * LOCKING: 210239281Sgonzo * DMA registers protected by internal mutex 211239281Sgonzo * 212239281Sgonzo * RETURNS: 213239281Sgonzo * nothing 214239281Sgonzo */ 215239281Sgonzostatic void 216239281Sgonzoti_sdma_intr(void *arg) 217239281Sgonzo{ 218239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 219239281Sgonzo uint32_t intr; 220239281Sgonzo uint32_t csr; 221239281Sgonzo unsigned int ch, j; 222239281Sgonzo struct ti_sdma_channel* channel; 223239281Sgonzo 224239281Sgonzo TI_SDMA_LOCK(sc); 225239281Sgonzo 226239281Sgonzo for (j = 0; j < NUM_DMA_IRQS; j++) { 227239281Sgonzo 228239281Sgonzo /* Get the flag interrupts (enabled) */ 229239281Sgonzo intr = ti_sdma_read_4(sc, DMA4_IRQSTATUS_L(j)); 230239281Sgonzo intr &= ti_sdma_read_4(sc, DMA4_IRQENABLE_L(j)); 231239281Sgonzo if (intr == 0x00000000) 232239281Sgonzo continue; 233239281Sgonzo 234239281Sgonzo /* Loop through checking the status bits */ 235239281Sgonzo for (ch = 0; ch < NUM_DMA_CHANNELS; ch++) { 236239281Sgonzo if (intr & (1 << ch)) { 237239281Sgonzo channel = &sc->sc_channel[ch]; 238239281Sgonzo 239239281Sgonzo /* Read the CSR regsiter and verify we don't have a spurious IRQ */ 240239281Sgonzo csr = ti_sdma_read_4(sc, DMA4_CSR(ch)); 241239281Sgonzo if (csr == 0) { 242239281Sgonzo device_printf(sc->sc_dev, "Spurious DMA IRQ for channel " 243239281Sgonzo "%d\n", ch); 244239281Sgonzo continue; 245239281Sgonzo } 246239281Sgonzo 247239281Sgonzo /* Sanity check this channel is active */ 248239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 249239281Sgonzo device_printf(sc->sc_dev, "IRQ %d for a non-activated " 250239281Sgonzo "channel %d\n", j, ch); 251239281Sgonzo continue; 252239281Sgonzo } 253239281Sgonzo 254239281Sgonzo /* Check the status error codes */ 255239281Sgonzo if (csr & DMA4_CSR_DROP) 256239281Sgonzo device_printf(sc->sc_dev, "Synchronization event drop " 257239281Sgonzo "occurred during the transfer on channel %u\n", 258239281Sgonzo ch); 259239281Sgonzo if (csr & DMA4_CSR_SECURE_ERR) 260239281Sgonzo device_printf(sc->sc_dev, "Secure transaction error event " 261239281Sgonzo "on channel %u\n", ch); 262239281Sgonzo if (csr & DMA4_CSR_MISALIGNED_ADRS_ERR) 263239281Sgonzo device_printf(sc->sc_dev, "Misaligned address error event " 264239281Sgonzo "on channel %u\n", ch); 265239281Sgonzo if (csr & DMA4_CSR_TRANS_ERR) { 266239281Sgonzo device_printf(sc->sc_dev, "Transaction error event on " 267239281Sgonzo "channel %u\n", ch); 268239281Sgonzo /* 269239281Sgonzo * Apparently according to linux code, there is an errata 270239281Sgonzo * that says the channel is not disabled upon this error. 271239281Sgonzo * They explicitly disable the channel here .. since I 272239281Sgonzo * haven't seen the errata, I'm going to ignore for now. 273239281Sgonzo */ 274239281Sgonzo } 275239281Sgonzo 276239281Sgonzo /* Clear the status flags for the IRQ */ 277239281Sgonzo ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK); 278239281Sgonzo ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch)); 279239281Sgonzo 280239281Sgonzo /* Call the callback for the given channel */ 281239281Sgonzo if (channel->callback) 282239281Sgonzo channel->callback(ch, csr, channel->callback_data); 283239281Sgonzo } 284239281Sgonzo } 285239281Sgonzo } 286239281Sgonzo 287239281Sgonzo TI_SDMA_UNLOCK(sc); 288239281Sgonzo 289239281Sgonzo return; 290239281Sgonzo} 291239281Sgonzo 292239281Sgonzo/** 293239281Sgonzo * ti_sdma_activate_channel - activates a DMA channel 294239281Sgonzo * @ch: upon return contains the channel allocated 295239281Sgonzo * @callback: a callback function to associate with the channel 296239281Sgonzo * @data: optional data supplied when the callback is called 297239281Sgonzo * 298239281Sgonzo * Simply activates a channel be enabling and writing default values to the 299239281Sgonzo * channel's register set. It doesn't start a transaction, just populates the 300239281Sgonzo * internal data structures and sets defaults. 301239281Sgonzo * 302239281Sgonzo * Note this function doesn't enable interrupts, for that you need to call 303239281Sgonzo * ti_sdma_enable_channel_irq(). If not using IRQ to detect the end of the 304239281Sgonzo * transfer, you can use ti_sdma_status_poll() to detect a change in the 305239281Sgonzo * status. 306239281Sgonzo * 307239281Sgonzo * A channel must be activated before any of the other DMA functions can be 308239281Sgonzo * called on it. 309239281Sgonzo * 310239281Sgonzo * LOCKING: 311239281Sgonzo * DMA registers protected by internal mutex 312239281Sgonzo * 313239281Sgonzo * RETURNS: 314239281Sgonzo * 0 on success, otherwise an error code 315239281Sgonzo */ 316239281Sgonzoint 317239281Sgonzoti_sdma_activate_channel(unsigned int *ch, 318239281Sgonzo void (*callback)(unsigned int ch, uint32_t status, void *data), 319239281Sgonzo void *data) 320239281Sgonzo{ 321239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 322239281Sgonzo struct ti_sdma_channel *channel = NULL; 323239281Sgonzo uint32_t addr; 324239281Sgonzo unsigned int i; 325239281Sgonzo 326239281Sgonzo /* Sanity check */ 327239281Sgonzo if (sc == NULL) 328239281Sgonzo return (ENOMEM); 329239281Sgonzo 330239281Sgonzo if (ch == NULL) 331239281Sgonzo return (EINVAL); 332239281Sgonzo 333239281Sgonzo TI_SDMA_LOCK(sc); 334239281Sgonzo 335239281Sgonzo /* Check to see if all channels are in use */ 336239281Sgonzo if (sc->sc_active_channels == 0xffffffff) { 337239281Sgonzo TI_SDMA_UNLOCK(sc); 338239281Sgonzo return (ENOMEM); 339239281Sgonzo } 340239281Sgonzo 341239281Sgonzo /* Find the first non-active channel */ 342239281Sgonzo for (i = 0; i < NUM_DMA_CHANNELS; i++) { 343239281Sgonzo if (!(sc->sc_active_channels & (0x1 << i))) { 344239281Sgonzo sc->sc_active_channels |= (0x1 << i); 345239281Sgonzo *ch = i; 346239281Sgonzo break; 347239281Sgonzo } 348239281Sgonzo } 349239281Sgonzo 350239281Sgonzo /* Get the channel struct and populate the fields */ 351239281Sgonzo channel = &sc->sc_channel[*ch]; 352239281Sgonzo 353239281Sgonzo channel->callback = callback; 354239281Sgonzo channel->callback_data = data; 355239281Sgonzo 356239281Sgonzo channel->need_reg_write = 1; 357239281Sgonzo 358239281Sgonzo /* Set the default configuration for the DMA channel */ 359239281Sgonzo channel->reg_csdp = DMA4_CSDP_DATA_TYPE(0x2) 360239281Sgonzo | DMA4_CSDP_SRC_BURST_MODE(0) 361239281Sgonzo | DMA4_CSDP_DST_BURST_MODE(0) 362239281Sgonzo | DMA4_CSDP_SRC_ENDIANISM(0) 363239281Sgonzo | DMA4_CSDP_DST_ENDIANISM(0) 364239281Sgonzo | DMA4_CSDP_WRITE_MODE(0) 365239281Sgonzo | DMA4_CSDP_SRC_PACKED(0) 366239281Sgonzo | DMA4_CSDP_DST_PACKED(0); 367239281Sgonzo 368239281Sgonzo channel->reg_ccr = DMA4_CCR_DST_ADDRESS_MODE(1) 369239281Sgonzo | DMA4_CCR_SRC_ADDRESS_MODE(1) 370239281Sgonzo | DMA4_CCR_READ_PRIORITY(0) 371239281Sgonzo | DMA4_CCR_WRITE_PRIORITY(0) 372239281Sgonzo | DMA4_CCR_SYNC_TRIGGER(0) 373239281Sgonzo | DMA4_CCR_FRAME_SYNC(0) 374239281Sgonzo | DMA4_CCR_BLOCK_SYNC(0); 375239281Sgonzo 376239281Sgonzo channel->reg_cicr = DMA4_CICR_TRANS_ERR_IE 377239281Sgonzo | DMA4_CICR_SECURE_ERR_IE 378239281Sgonzo | DMA4_CICR_SUPERVISOR_ERR_IE 379239281Sgonzo | DMA4_CICR_MISALIGNED_ADRS_ERR_IE; 380239281Sgonzo 381239281Sgonzo /* Clear all the channel registers, this should abort any transaction */ 382239281Sgonzo for (addr = DMA4_CCR(*ch); addr <= DMA4_COLOR(*ch); addr += 4) 383239281Sgonzo ti_sdma_write_4(sc, addr, 0x00000000); 384239281Sgonzo 385239281Sgonzo TI_SDMA_UNLOCK(sc); 386239281Sgonzo 387239281Sgonzo return 0; 388239281Sgonzo} 389239281Sgonzo 390239281Sgonzo/** 391239281Sgonzo * ti_sdma_deactivate_channel - deactivates a channel 392239281Sgonzo * @ch: the channel to deactivate 393239281Sgonzo * 394239281Sgonzo * 395239281Sgonzo * 396239281Sgonzo * LOCKING: 397239281Sgonzo * DMA registers protected by internal mutex 398239281Sgonzo * 399239281Sgonzo * RETURNS: 400239281Sgonzo * EH_HANDLED or EH_NOT_HANDLED 401239281Sgonzo */ 402239281Sgonzoint 403239281Sgonzoti_sdma_deactivate_channel(unsigned int ch) 404239281Sgonzo{ 405239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 406239281Sgonzo unsigned int j; 407239281Sgonzo unsigned int addr; 408239281Sgonzo 409239281Sgonzo /* Sanity check */ 410239281Sgonzo if (sc == NULL) 411239281Sgonzo return (ENOMEM); 412239281Sgonzo 413239281Sgonzo TI_SDMA_LOCK(sc); 414239281Sgonzo 415239281Sgonzo /* First check if the channel is currently active */ 416239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 417239281Sgonzo TI_SDMA_UNLOCK(sc); 418239281Sgonzo return (EBUSY); 419239281Sgonzo } 420239281Sgonzo 421239281Sgonzo /* Mark the channel as inactive */ 422239281Sgonzo sc->sc_active_channels &= ~(1 << ch); 423239281Sgonzo 424239281Sgonzo /* Disable all DMA interrupts for the channel. */ 425239281Sgonzo ti_sdma_write_4(sc, DMA4_CICR(ch), 0); 426239281Sgonzo 427239281Sgonzo /* Make sure the DMA transfer is stopped. */ 428239281Sgonzo ti_sdma_write_4(sc, DMA4_CCR(ch), 0); 429239281Sgonzo 430239281Sgonzo /* Clear the CSR register and IRQ status register */ 431239281Sgonzo ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK); 432239281Sgonzo for (j = 0; j < NUM_DMA_IRQS; j++) { 433239281Sgonzo ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch)); 434239281Sgonzo } 435239281Sgonzo 436239281Sgonzo /* Clear all the channel registers, this should abort any transaction */ 437239281Sgonzo for (addr = DMA4_CCR(ch); addr <= DMA4_COLOR(ch); addr += 4) 438239281Sgonzo ti_sdma_write_4(sc, addr, 0x00000000); 439239281Sgonzo 440239281Sgonzo TI_SDMA_UNLOCK(sc); 441239281Sgonzo 442239281Sgonzo return 0; 443239281Sgonzo} 444239281Sgonzo 445239281Sgonzo/** 446239281Sgonzo * ti_sdma_disable_channel_irq - disables IRQ's on the given channel 447239281Sgonzo * @ch: the channel to disable IRQ's on 448239281Sgonzo * 449239281Sgonzo * Disable interupt generation for the given channel. 450239281Sgonzo * 451239281Sgonzo * LOCKING: 452239281Sgonzo * DMA registers protected by internal mutex 453239281Sgonzo * 454239281Sgonzo * RETURNS: 455239281Sgonzo * EH_HANDLED or EH_NOT_HANDLED 456239281Sgonzo */ 457239281Sgonzoint 458239281Sgonzoti_sdma_disable_channel_irq(unsigned int ch) 459239281Sgonzo{ 460239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 461239281Sgonzo uint32_t irq_enable; 462239281Sgonzo unsigned int j; 463239281Sgonzo 464239281Sgonzo /* Sanity check */ 465239281Sgonzo if (sc == NULL) 466239281Sgonzo return (ENOMEM); 467239281Sgonzo 468239281Sgonzo TI_SDMA_LOCK(sc); 469239281Sgonzo 470239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 471239281Sgonzo TI_SDMA_UNLOCK(sc); 472239281Sgonzo return (EINVAL); 473239281Sgonzo } 474239281Sgonzo 475239281Sgonzo /* Disable all the individual error conditions */ 476239281Sgonzo sc->sc_channel[ch].reg_cicr = 0x0000; 477239281Sgonzo ti_sdma_write_4(sc, DMA4_CICR(ch), 0x0000); 478239281Sgonzo 479239281Sgonzo /* Disable the channel interrupt enable */ 480239281Sgonzo for (j = 0; j < NUM_DMA_IRQS; j++) { 481239281Sgonzo irq_enable = ti_sdma_read_4(sc, DMA4_IRQENABLE_L(j)); 482239281Sgonzo irq_enable &= ~(1 << ch); 483239281Sgonzo 484239281Sgonzo ti_sdma_write_4(sc, DMA4_IRQENABLE_L(j), irq_enable); 485239281Sgonzo } 486239281Sgonzo 487239281Sgonzo /* Indicate the registers need to be rewritten on the next transaction */ 488239281Sgonzo sc->sc_channel[ch].need_reg_write = 1; 489239281Sgonzo 490239281Sgonzo TI_SDMA_UNLOCK(sc); 491239281Sgonzo 492239281Sgonzo return (0); 493239281Sgonzo} 494239281Sgonzo 495239281Sgonzo/** 496239281Sgonzo * ti_sdma_disable_channel_irq - enables IRQ's on the given channel 497239281Sgonzo * @ch: the channel to enable IRQ's on 498239281Sgonzo * @flags: bitmask of interrupt types to enable 499239281Sgonzo * 500239281Sgonzo * Flags can be a bitmask of the following options: 501239281Sgonzo * DMA_IRQ_FLAG_DROP 502239281Sgonzo * DMA_IRQ_FLAG_HALF_FRAME_COMPL 503239281Sgonzo * DMA_IRQ_FLAG_FRAME_COMPL 504239281Sgonzo * DMA_IRQ_FLAG_START_LAST_FRAME 505239281Sgonzo * DMA_IRQ_FLAG_BLOCK_COMPL 506239281Sgonzo * DMA_IRQ_FLAG_ENDOF_PKT 507239281Sgonzo * DMA_IRQ_FLAG_DRAIN 508239281Sgonzo * 509239281Sgonzo * 510239281Sgonzo * LOCKING: 511239281Sgonzo * DMA registers protected by internal mutex 512239281Sgonzo * 513239281Sgonzo * RETURNS: 514239281Sgonzo * EH_HANDLED or EH_NOT_HANDLED 515239281Sgonzo */ 516239281Sgonzoint 517239281Sgonzoti_sdma_enable_channel_irq(unsigned int ch, uint32_t flags) 518239281Sgonzo{ 519239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 520239281Sgonzo uint32_t irq_enable; 521239281Sgonzo 522239281Sgonzo /* Sanity check */ 523239281Sgonzo if (sc == NULL) 524239281Sgonzo return (ENOMEM); 525239281Sgonzo 526239281Sgonzo TI_SDMA_LOCK(sc); 527239281Sgonzo 528239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 529239281Sgonzo TI_SDMA_UNLOCK(sc); 530239281Sgonzo return (EINVAL); 531239281Sgonzo } 532239281Sgonzo 533239281Sgonzo /* Always enable the error interrupts if we have interrupts enabled */ 534239281Sgonzo flags |= DMA4_CICR_TRANS_ERR_IE | DMA4_CICR_SECURE_ERR_IE | 535239281Sgonzo DMA4_CICR_SUPERVISOR_ERR_IE | DMA4_CICR_MISALIGNED_ADRS_ERR_IE; 536239281Sgonzo 537239281Sgonzo sc->sc_channel[ch].reg_cicr = flags; 538239281Sgonzo 539239281Sgonzo /* Write the values to the register */ 540239281Sgonzo ti_sdma_write_4(sc, DMA4_CICR(ch), flags); 541239281Sgonzo 542239281Sgonzo /* Enable the channel interrupt enable */ 543239281Sgonzo irq_enable = ti_sdma_read_4(sc, DMA4_IRQENABLE_L(0)); 544239281Sgonzo irq_enable |= (1 << ch); 545239281Sgonzo 546239281Sgonzo ti_sdma_write_4(sc, DMA4_IRQENABLE_L(0), irq_enable); 547239281Sgonzo 548239281Sgonzo /* Indicate the registers need to be rewritten on the next transaction */ 549239281Sgonzo sc->sc_channel[ch].need_reg_write = 1; 550239281Sgonzo 551239281Sgonzo TI_SDMA_UNLOCK(sc); 552239281Sgonzo 553239281Sgonzo return (0); 554239281Sgonzo} 555239281Sgonzo 556239281Sgonzo/** 557239281Sgonzo * ti_sdma_get_channel_status - returns the status of a given channel 558239281Sgonzo * @ch: the channel number to get the status of 559239281Sgonzo * @status: upon return will contain the status bitmask, see below for possible 560239281Sgonzo * values. 561239281Sgonzo * 562239281Sgonzo * DMA_STATUS_DROP 563239281Sgonzo * DMA_STATUS_HALF 564239281Sgonzo * DMA_STATUS_FRAME 565239281Sgonzo * DMA_STATUS_LAST 566239281Sgonzo * DMA_STATUS_BLOCK 567239281Sgonzo * DMA_STATUS_SYNC 568239281Sgonzo * DMA_STATUS_PKT 569239281Sgonzo * DMA_STATUS_TRANS_ERR 570239281Sgonzo * DMA_STATUS_SECURE_ERR 571239281Sgonzo * DMA_STATUS_SUPERVISOR_ERR 572239281Sgonzo * DMA_STATUS_MISALIGNED_ADRS_ERR 573239281Sgonzo * DMA_STATUS_DRAIN_END 574239281Sgonzo * 575239281Sgonzo * 576239281Sgonzo * LOCKING: 577239281Sgonzo * DMA registers protected by internal mutex 578239281Sgonzo * 579239281Sgonzo * RETURNS: 580239281Sgonzo * EH_HANDLED or EH_NOT_HANDLED 581239281Sgonzo */ 582239281Sgonzoint 583239281Sgonzoti_sdma_get_channel_status(unsigned int ch, uint32_t *status) 584239281Sgonzo{ 585239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 586239281Sgonzo uint32_t csr; 587239281Sgonzo 588239281Sgonzo /* Sanity check */ 589239281Sgonzo if (sc == NULL) 590239281Sgonzo return (ENOMEM); 591239281Sgonzo 592239281Sgonzo TI_SDMA_LOCK(sc); 593239281Sgonzo 594239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 595239281Sgonzo TI_SDMA_UNLOCK(sc); 596239281Sgonzo return (EINVAL); 597239281Sgonzo } 598239281Sgonzo 599239281Sgonzo TI_SDMA_UNLOCK(sc); 600239281Sgonzo 601239281Sgonzo csr = ti_sdma_read_4(sc, DMA4_CSR(ch)); 602239281Sgonzo 603239281Sgonzo if (status != NULL) 604239281Sgonzo *status = csr; 605239281Sgonzo 606239281Sgonzo return (0); 607239281Sgonzo} 608239281Sgonzo 609239281Sgonzo/** 610239281Sgonzo * ti_sdma_start_xfer - starts a DMA transfer 611239281Sgonzo * @ch: the channel number to set the endianess of 612239281Sgonzo * @src_paddr: the source phsyical address 613239281Sgonzo * @dst_paddr: the destination phsyical address 614239281Sgonzo * @frmcnt: the number of frames per block 615239281Sgonzo * @elmcnt: the number of elements in a frame, an element is either an 8, 16 616239281Sgonzo * or 32-bit value as defined by ti_sdma_set_xfer_burst() 617239281Sgonzo * 618239281Sgonzo * 619239281Sgonzo * LOCKING: 620239281Sgonzo * DMA registers protected by internal mutex 621239281Sgonzo * 622239281Sgonzo * RETURNS: 623239281Sgonzo * EH_HANDLED or EH_NOT_HANDLED 624239281Sgonzo */ 625239281Sgonzoint 626239281Sgonzoti_sdma_start_xfer(unsigned int ch, unsigned int src_paddr, 627239281Sgonzo unsigned long dst_paddr, 628239281Sgonzo unsigned int frmcnt, unsigned int elmcnt) 629239281Sgonzo{ 630239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 631239281Sgonzo struct ti_sdma_channel *channel; 632239281Sgonzo uint32_t ccr; 633239281Sgonzo 634239281Sgonzo /* Sanity check */ 635239281Sgonzo if (sc == NULL) 636239281Sgonzo return (ENOMEM); 637239281Sgonzo 638239281Sgonzo TI_SDMA_LOCK(sc); 639239281Sgonzo 640239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 641239281Sgonzo TI_SDMA_UNLOCK(sc); 642239281Sgonzo return (EINVAL); 643239281Sgonzo } 644239281Sgonzo 645239281Sgonzo channel = &sc->sc_channel[ch]; 646239281Sgonzo 647239281Sgonzo /* a) Write the CSDP register */ 648239281Sgonzo ti_sdma_write_4(sc, DMA4_CSDP(ch), 649239281Sgonzo channel->reg_csdp | DMA4_CSDP_WRITE_MODE(1)); 650239281Sgonzo 651239281Sgonzo /* b) Set the number of element per frame CEN[23:0] */ 652239281Sgonzo ti_sdma_write_4(sc, DMA4_CEN(ch), elmcnt); 653239281Sgonzo 654239281Sgonzo /* c) Set the number of frame per block CFN[15:0] */ 655239281Sgonzo ti_sdma_write_4(sc, DMA4_CFN(ch), frmcnt); 656239281Sgonzo 657239281Sgonzo /* d) Set the Source/dest start address index CSSA[31:0]/CDSA[31:0] */ 658239281Sgonzo ti_sdma_write_4(sc, DMA4_CSSA(ch), src_paddr); 659239281Sgonzo ti_sdma_write_4(sc, DMA4_CDSA(ch), dst_paddr); 660239281Sgonzo 661239281Sgonzo /* e) Write the CCR register */ 662239281Sgonzo ti_sdma_write_4(sc, DMA4_CCR(ch), channel->reg_ccr); 663239281Sgonzo 664239281Sgonzo /* f) - Set the source element index increment CSEI[15:0] */ 665239281Sgonzo ti_sdma_write_4(sc, DMA4_CSE(ch), 0x0001); 666239281Sgonzo 667239281Sgonzo /* - Set the source frame index increment CSFI[15:0] */ 668239281Sgonzo ti_sdma_write_4(sc, DMA4_CSF(ch), 0x0001); 669239281Sgonzo 670239281Sgonzo /* - Set the destination element index increment CDEI[15:0]*/ 671239281Sgonzo ti_sdma_write_4(sc, DMA4_CDE(ch), 0x0001); 672239281Sgonzo 673239281Sgonzo /* - Set the destination frame index increment CDFI[31:0] */ 674239281Sgonzo ti_sdma_write_4(sc, DMA4_CDF(ch), 0x0001); 675239281Sgonzo 676239281Sgonzo /* Clear the status register */ 677239281Sgonzo ti_sdma_write_4(sc, DMA4_CSR(ch), 0x1FFE); 678239281Sgonzo 679239281Sgonzo /* Write the start-bit and away we go */ 680239281Sgonzo ccr = ti_sdma_read_4(sc, DMA4_CCR(ch)); 681239281Sgonzo ccr |= (1 << 7); 682239281Sgonzo ti_sdma_write_4(sc, DMA4_CCR(ch), ccr); 683239281Sgonzo 684239281Sgonzo /* Clear the reg write flag */ 685239281Sgonzo channel->need_reg_write = 0; 686239281Sgonzo 687239281Sgonzo TI_SDMA_UNLOCK(sc); 688239281Sgonzo 689239281Sgonzo return (0); 690239281Sgonzo} 691239281Sgonzo 692239281Sgonzo/** 693239281Sgonzo * ti_sdma_start_xfer_packet - starts a packet DMA transfer 694239281Sgonzo * @ch: the channel number to use for the transfer 695239281Sgonzo * @src_paddr: the source physical address 696239281Sgonzo * @dst_paddr: the destination physical address 697239281Sgonzo * @frmcnt: the number of frames to transfer 698239281Sgonzo * @elmcnt: the number of elements in a frame, an element is either an 8, 16 699239281Sgonzo * or 32-bit value as defined by ti_sdma_set_xfer_burst() 700239281Sgonzo * @pktsize: the number of elements in each transfer packet 701239281Sgonzo * 702239281Sgonzo * The @frmcnt and @elmcnt define the overall number of bytes to transfer, 703239281Sgonzo * typically @frmcnt is 1 and @elmcnt contains the total number of elements. 704239281Sgonzo * @pktsize is the size of each individual packet, there might be multiple 705239281Sgonzo * packets per transfer. i.e. for the following with element size of 32-bits 706239281Sgonzo * 707239281Sgonzo * frmcnt = 1, elmcnt = 512, pktsize = 128 708239281Sgonzo * 709239281Sgonzo * Total transfer bytes = 1 * 512 = 512 elements or 2048 bytes 710239281Sgonzo * Packets transfered = 128 / 512 = 4 711239281Sgonzo * 712239281Sgonzo * 713239281Sgonzo * LOCKING: 714239281Sgonzo * DMA registers protected by internal mutex 715239281Sgonzo * 716239281Sgonzo * RETURNS: 717239281Sgonzo * EH_HANDLED or EH_NOT_HANDLED 718239281Sgonzo */ 719239281Sgonzoint 720239281Sgonzoti_sdma_start_xfer_packet(unsigned int ch, unsigned int src_paddr, 721239281Sgonzo unsigned long dst_paddr, unsigned int frmcnt, 722239281Sgonzo unsigned int elmcnt, unsigned int pktsize) 723239281Sgonzo{ 724239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 725239281Sgonzo struct ti_sdma_channel *channel; 726239281Sgonzo uint32_t ccr; 727239281Sgonzo 728239281Sgonzo /* Sanity check */ 729239281Sgonzo if (sc == NULL) 730239281Sgonzo return (ENOMEM); 731239281Sgonzo 732239281Sgonzo TI_SDMA_LOCK(sc); 733239281Sgonzo 734239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 735239281Sgonzo TI_SDMA_UNLOCK(sc); 736239281Sgonzo return (EINVAL); 737239281Sgonzo } 738239281Sgonzo 739239281Sgonzo channel = &sc->sc_channel[ch]; 740239281Sgonzo 741239281Sgonzo /* a) Write the CSDP register */ 742239281Sgonzo if (channel->need_reg_write) 743239281Sgonzo ti_sdma_write_4(sc, DMA4_CSDP(ch), 744239281Sgonzo channel->reg_csdp | DMA4_CSDP_WRITE_MODE(1)); 745239281Sgonzo 746239281Sgonzo /* b) Set the number of elements to transfer CEN[23:0] */ 747239281Sgonzo ti_sdma_write_4(sc, DMA4_CEN(ch), elmcnt); 748239281Sgonzo 749239281Sgonzo /* c) Set the number of frames to transfer CFN[15:0] */ 750239281Sgonzo ti_sdma_write_4(sc, DMA4_CFN(ch), frmcnt); 751239281Sgonzo 752239281Sgonzo /* d) Set the Source/dest start address index CSSA[31:0]/CDSA[31:0] */ 753239281Sgonzo ti_sdma_write_4(sc, DMA4_CSSA(ch), src_paddr); 754239281Sgonzo ti_sdma_write_4(sc, DMA4_CDSA(ch), dst_paddr); 755239281Sgonzo 756239281Sgonzo /* e) Write the CCR register */ 757239281Sgonzo ti_sdma_write_4(sc, DMA4_CCR(ch), 758239281Sgonzo channel->reg_ccr | DMA4_CCR_PACKET_TRANS); 759239281Sgonzo 760239281Sgonzo /* f) - Set the source element index increment CSEI[15:0] */ 761239281Sgonzo ti_sdma_write_4(sc, DMA4_CSE(ch), 0x0001); 762239281Sgonzo 763239281Sgonzo /* - Set the packet size, this is dependent on the sync source */ 764239281Sgonzo if (channel->reg_ccr & DMA4_CCR_SEL_SRC_DST_SYNC(1)) 765239281Sgonzo ti_sdma_write_4(sc, DMA4_CSF(ch), pktsize); 766239281Sgonzo else 767239281Sgonzo ti_sdma_write_4(sc, DMA4_CDF(ch), pktsize); 768239281Sgonzo 769239281Sgonzo /* - Set the destination frame index increment CDFI[31:0] */ 770239281Sgonzo ti_sdma_write_4(sc, DMA4_CDE(ch), 0x0001); 771239281Sgonzo 772239281Sgonzo /* Clear the status register */ 773239281Sgonzo ti_sdma_write_4(sc, DMA4_CSR(ch), 0x1FFE); 774239281Sgonzo 775239281Sgonzo /* Write the start-bit and away we go */ 776239281Sgonzo ccr = ti_sdma_read_4(sc, DMA4_CCR(ch)); 777239281Sgonzo ccr |= (1 << 7); 778239281Sgonzo ti_sdma_write_4(sc, DMA4_CCR(ch), ccr); 779239281Sgonzo 780239281Sgonzo /* Clear the reg write flag */ 781239281Sgonzo channel->need_reg_write = 0; 782239281Sgonzo 783239281Sgonzo TI_SDMA_UNLOCK(sc); 784239281Sgonzo 785239281Sgonzo return (0); 786239281Sgonzo} 787239281Sgonzo 788239281Sgonzo/** 789239281Sgonzo * ti_sdma_stop_xfer - stops any currently active transfers 790239281Sgonzo * @ch: the channel number to set the endianess of 791239281Sgonzo * 792239281Sgonzo * This function call is effectively a NOP if no transaction is in progress. 793239281Sgonzo * 794239281Sgonzo * LOCKING: 795239281Sgonzo * DMA registers protected by internal mutex 796239281Sgonzo * 797239281Sgonzo * RETURNS: 798239281Sgonzo * EH_HANDLED or EH_NOT_HANDLED 799239281Sgonzo */ 800239281Sgonzoint 801239281Sgonzoti_sdma_stop_xfer(unsigned int ch) 802239281Sgonzo{ 803239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 804239281Sgonzo unsigned int j; 805239281Sgonzo 806239281Sgonzo /* Sanity check */ 807239281Sgonzo if (sc == NULL) 808239281Sgonzo return (ENOMEM); 809239281Sgonzo 810239281Sgonzo TI_SDMA_LOCK(sc); 811239281Sgonzo 812239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 813239281Sgonzo TI_SDMA_UNLOCK(sc); 814239281Sgonzo return (EINVAL); 815239281Sgonzo } 816239281Sgonzo 817239281Sgonzo /* Disable all DMA interrupts for the channel. */ 818239281Sgonzo ti_sdma_write_4(sc, DMA4_CICR(ch), 0); 819239281Sgonzo 820239281Sgonzo /* Make sure the DMA transfer is stopped. */ 821239281Sgonzo ti_sdma_write_4(sc, DMA4_CCR(ch), 0); 822239281Sgonzo 823239281Sgonzo /* Clear the CSR register and IRQ status register */ 824239281Sgonzo ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK); 825239281Sgonzo for (j = 0; j < NUM_DMA_IRQS; j++) { 826239281Sgonzo ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch)); 827239281Sgonzo } 828239281Sgonzo 829239281Sgonzo /* Configuration registers need to be re-written on the next xfer */ 830239281Sgonzo sc->sc_channel[ch].need_reg_write = 1; 831239281Sgonzo 832239281Sgonzo TI_SDMA_UNLOCK(sc); 833239281Sgonzo 834239281Sgonzo return (0); 835239281Sgonzo} 836239281Sgonzo 837239281Sgonzo/** 838239281Sgonzo * ti_sdma_set_xfer_endianess - sets the endianess of subsequent transfers 839239281Sgonzo * @ch: the channel number to set the endianess of 840239281Sgonzo * @src: the source endianess (either DMA_ENDIAN_LITTLE or DMA_ENDIAN_BIG) 841239281Sgonzo * @dst: the destination endianess (either DMA_ENDIAN_LITTLE or DMA_ENDIAN_BIG) 842239281Sgonzo * 843239281Sgonzo * 844239281Sgonzo * LOCKING: 845239281Sgonzo * DMA registers protected by internal mutex 846239281Sgonzo * 847239281Sgonzo * RETURNS: 848239281Sgonzo * EH_HANDLED or EH_NOT_HANDLED 849239281Sgonzo */ 850239281Sgonzoint 851239281Sgonzoti_sdma_set_xfer_endianess(unsigned int ch, unsigned int src, unsigned int dst) 852239281Sgonzo{ 853239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 854239281Sgonzo 855239281Sgonzo /* Sanity check */ 856239281Sgonzo if (sc == NULL) 857239281Sgonzo return (ENOMEM); 858239281Sgonzo 859239281Sgonzo TI_SDMA_LOCK(sc); 860239281Sgonzo 861239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 862239281Sgonzo TI_SDMA_UNLOCK(sc); 863239281Sgonzo return (EINVAL); 864239281Sgonzo } 865239281Sgonzo 866239281Sgonzo sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_SRC_ENDIANISM(1); 867239281Sgonzo sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_SRC_ENDIANISM(src); 868239281Sgonzo 869239281Sgonzo sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DST_ENDIANISM(1); 870239281Sgonzo sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DST_ENDIANISM(dst); 871239281Sgonzo 872239281Sgonzo sc->sc_channel[ch].need_reg_write = 1; 873239281Sgonzo 874239281Sgonzo TI_SDMA_UNLOCK(sc); 875239281Sgonzo 876239281Sgonzo return 0; 877239281Sgonzo} 878239281Sgonzo 879239281Sgonzo/** 880239281Sgonzo * ti_sdma_set_xfer_burst - sets the source and destination element size 881239281Sgonzo * @ch: the channel number to set the burst settings of 882239281Sgonzo * @src: the source endianess (either DMA_BURST_NONE, DMA_BURST_16, DMA_BURST_32 883239281Sgonzo * or DMA_BURST_64) 884239281Sgonzo * @dst: the destination endianess (either DMA_BURST_NONE, DMA_BURST_16, 885239281Sgonzo * DMA_BURST_32 or DMA_BURST_64) 886239281Sgonzo * 887239281Sgonzo * This function sets the size of the elements for all subsequent transfers. 888239281Sgonzo * 889239281Sgonzo * LOCKING: 890239281Sgonzo * DMA registers protected by internal mutex 891239281Sgonzo * 892239281Sgonzo * RETURNS: 893239281Sgonzo * EH_HANDLED or EH_NOT_HANDLED 894239281Sgonzo */ 895239281Sgonzoint 896239281Sgonzoti_sdma_set_xfer_burst(unsigned int ch, unsigned int src, unsigned int dst) 897239281Sgonzo{ 898239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 899239281Sgonzo 900239281Sgonzo /* Sanity check */ 901239281Sgonzo if (sc == NULL) 902239281Sgonzo return (ENOMEM); 903239281Sgonzo 904239281Sgonzo TI_SDMA_LOCK(sc); 905239281Sgonzo 906239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 907239281Sgonzo TI_SDMA_UNLOCK(sc); 908239281Sgonzo return (EINVAL); 909239281Sgonzo } 910239281Sgonzo 911239281Sgonzo sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_SRC_BURST_MODE(0x3); 912239281Sgonzo sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_SRC_BURST_MODE(src); 913239281Sgonzo 914239281Sgonzo sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DST_BURST_MODE(0x3); 915239281Sgonzo sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DST_BURST_MODE(dst); 916239281Sgonzo 917239281Sgonzo sc->sc_channel[ch].need_reg_write = 1; 918239281Sgonzo 919239281Sgonzo TI_SDMA_UNLOCK(sc); 920239281Sgonzo 921239281Sgonzo return 0; 922239281Sgonzo} 923239281Sgonzo 924239281Sgonzo/** 925239281Sgonzo * ti_sdma_set_xfer_data_type - driver attach function 926239281Sgonzo * @ch: the channel number to set the endianess of 927239281Sgonzo * @type: the xfer data type (either DMA_DATA_8BITS_SCALAR, DMA_DATA_16BITS_SCALAR 928239281Sgonzo * or DMA_DATA_32BITS_SCALAR) 929239281Sgonzo * 930239281Sgonzo * 931239281Sgonzo * LOCKING: 932239281Sgonzo * DMA registers protected by internal mutex 933239281Sgonzo * 934239281Sgonzo * RETURNS: 935239281Sgonzo * EH_HANDLED or EH_NOT_HANDLED 936239281Sgonzo */ 937239281Sgonzoint 938239281Sgonzoti_sdma_set_xfer_data_type(unsigned int ch, unsigned int type) 939239281Sgonzo{ 940239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 941239281Sgonzo 942239281Sgonzo /* Sanity check */ 943239281Sgonzo if (sc == NULL) 944239281Sgonzo return (ENOMEM); 945239281Sgonzo 946239281Sgonzo TI_SDMA_LOCK(sc); 947239281Sgonzo 948239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 949239281Sgonzo TI_SDMA_UNLOCK(sc); 950239281Sgonzo return (EINVAL); 951239281Sgonzo } 952239281Sgonzo 953239281Sgonzo sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DATA_TYPE(0x3); 954239281Sgonzo sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DATA_TYPE(type); 955239281Sgonzo 956239281Sgonzo sc->sc_channel[ch].need_reg_write = 1; 957239281Sgonzo 958239281Sgonzo TI_SDMA_UNLOCK(sc); 959239281Sgonzo 960239281Sgonzo return 0; 961239281Sgonzo} 962239281Sgonzo 963239281Sgonzo/** 964239281Sgonzo * ti_sdma_set_callback - driver attach function 965239281Sgonzo * @dev: dma device handle 966239281Sgonzo * 967239281Sgonzo * 968239281Sgonzo * 969239281Sgonzo * LOCKING: 970239281Sgonzo * DMA registers protected by internal mutex 971239281Sgonzo * 972239281Sgonzo * RETURNS: 973239281Sgonzo * EH_HANDLED or EH_NOT_HANDLED 974239281Sgonzo */ 975239281Sgonzoint 976239281Sgonzoti_sdma_set_callback(unsigned int ch, 977239281Sgonzo void (*callback)(unsigned int ch, uint32_t status, void *data), 978239281Sgonzo void *data) 979239281Sgonzo{ 980239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 981239281Sgonzo 982239281Sgonzo /* Sanity check */ 983239281Sgonzo if (sc == NULL) 984239281Sgonzo return (ENOMEM); 985239281Sgonzo 986239281Sgonzo TI_SDMA_LOCK(sc); 987239281Sgonzo 988239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 989239281Sgonzo TI_SDMA_UNLOCK(sc); 990239281Sgonzo return (EINVAL); 991239281Sgonzo } 992239281Sgonzo 993239281Sgonzo sc->sc_channel[ch].callback = callback; 994239281Sgonzo sc->sc_channel[ch].callback_data = data; 995239281Sgonzo 996239281Sgonzo sc->sc_channel[ch].need_reg_write = 1; 997239281Sgonzo 998239281Sgonzo TI_SDMA_UNLOCK(sc); 999239281Sgonzo 1000239281Sgonzo return 0; 1001239281Sgonzo} 1002239281Sgonzo 1003239281Sgonzo/** 1004239281Sgonzo * ti_sdma_sync_params - sets channel sync settings 1005239281Sgonzo * @ch: the channel number to set the sync on 1006239281Sgonzo * @trigger: the number of the sync trigger, this depends on what other H/W 1007239281Sgonzo * module is triggering/receiving the DMA transactions 1008239281Sgonzo * @mode: flags describing the sync mode to use, it may have one or more of 1009239281Sgonzo * the following bits set; TI_SDMA_SYNC_FRAME, 1010239281Sgonzo * TI_SDMA_SYNC_BLOCK, TI_SDMA_SYNC_TRIG_ON_SRC. 1011239281Sgonzo * 1012239281Sgonzo * 1013239281Sgonzo * 1014239281Sgonzo * LOCKING: 1015239281Sgonzo * DMA registers protected by internal mutex 1016239281Sgonzo * 1017239281Sgonzo * RETURNS: 1018239281Sgonzo * EH_HANDLED or EH_NOT_HANDLED 1019239281Sgonzo */ 1020239281Sgonzoint 1021239281Sgonzoti_sdma_sync_params(unsigned int ch, unsigned int trigger, unsigned int mode) 1022239281Sgonzo{ 1023239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 1024239281Sgonzo uint32_t ccr; 1025239281Sgonzo 1026239281Sgonzo /* Sanity check */ 1027239281Sgonzo if (sc == NULL) 1028239281Sgonzo return (ENOMEM); 1029239281Sgonzo 1030239281Sgonzo TI_SDMA_LOCK(sc); 1031239281Sgonzo 1032239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 1033239281Sgonzo TI_SDMA_UNLOCK(sc); 1034239281Sgonzo return (EINVAL); 1035239281Sgonzo } 1036239281Sgonzo 1037239281Sgonzo ccr = sc->sc_channel[ch].reg_ccr; 1038239281Sgonzo 1039239281Sgonzo ccr &= ~DMA4_CCR_SYNC_TRIGGER(0x7F); 1040239281Sgonzo ccr |= DMA4_CCR_SYNC_TRIGGER(trigger + 1); 1041239281Sgonzo 1042239281Sgonzo if (mode & TI_SDMA_SYNC_FRAME) 1043239281Sgonzo ccr |= DMA4_CCR_FRAME_SYNC(1); 1044239281Sgonzo else 1045239281Sgonzo ccr &= ~DMA4_CCR_FRAME_SYNC(1); 1046239281Sgonzo 1047239281Sgonzo if (mode & TI_SDMA_SYNC_BLOCK) 1048239281Sgonzo ccr |= DMA4_CCR_BLOCK_SYNC(1); 1049239281Sgonzo else 1050239281Sgonzo ccr &= ~DMA4_CCR_BLOCK_SYNC(1); 1051239281Sgonzo 1052239281Sgonzo if (mode & TI_SDMA_SYNC_TRIG_ON_SRC) 1053239281Sgonzo ccr |= DMA4_CCR_SEL_SRC_DST_SYNC(1); 1054239281Sgonzo else 1055239281Sgonzo ccr &= ~DMA4_CCR_SEL_SRC_DST_SYNC(1); 1056239281Sgonzo 1057239281Sgonzo sc->sc_channel[ch].reg_ccr = ccr; 1058239281Sgonzo 1059239281Sgonzo sc->sc_channel[ch].need_reg_write = 1; 1060239281Sgonzo 1061239281Sgonzo TI_SDMA_UNLOCK(sc); 1062239281Sgonzo 1063239281Sgonzo return 0; 1064239281Sgonzo} 1065239281Sgonzo 1066239281Sgonzo/** 1067239281Sgonzo * ti_sdma_set_addr_mode - driver attach function 1068239281Sgonzo * @ch: the channel number to set the endianess of 1069239281Sgonzo * @rd_mode: the xfer source addressing mode (either DMA_ADDR_CONSTANT, 1070239281Sgonzo * DMA_ADDR_POST_INCREMENT, DMA_ADDR_SINGLE_INDEX or 1071239281Sgonzo * DMA_ADDR_DOUBLE_INDEX) 1072239281Sgonzo * @wr_mode: the xfer destination addressing mode (either DMA_ADDR_CONSTANT, 1073239281Sgonzo * DMA_ADDR_POST_INCREMENT, DMA_ADDR_SINGLE_INDEX or 1074239281Sgonzo * DMA_ADDR_DOUBLE_INDEX) 1075239281Sgonzo * 1076239281Sgonzo * 1077239281Sgonzo * LOCKING: 1078239281Sgonzo * DMA registers protected by internal mutex 1079239281Sgonzo * 1080239281Sgonzo * RETURNS: 1081239281Sgonzo * EH_HANDLED or EH_NOT_HANDLED 1082239281Sgonzo */ 1083239281Sgonzoint 1084239281Sgonzoti_sdma_set_addr_mode(unsigned int ch, unsigned int src_mode, 1085239281Sgonzo unsigned int dst_mode) 1086239281Sgonzo{ 1087239281Sgonzo struct ti_sdma_softc *sc = ti_sdma_sc; 1088239281Sgonzo uint32_t ccr; 1089239281Sgonzo 1090239281Sgonzo /* Sanity check */ 1091239281Sgonzo if (sc == NULL) 1092239281Sgonzo return (ENOMEM); 1093239281Sgonzo 1094239281Sgonzo TI_SDMA_LOCK(sc); 1095239281Sgonzo 1096239281Sgonzo if ((sc->sc_active_channels & (1 << ch)) == 0) { 1097239281Sgonzo TI_SDMA_UNLOCK(sc); 1098239281Sgonzo return (EINVAL); 1099239281Sgonzo } 1100239281Sgonzo 1101239281Sgonzo ccr = sc->sc_channel[ch].reg_ccr; 1102239281Sgonzo 1103239281Sgonzo ccr &= ~DMA4_CCR_SRC_ADDRESS_MODE(0x3); 1104239281Sgonzo ccr |= DMA4_CCR_SRC_ADDRESS_MODE(src_mode); 1105239281Sgonzo 1106239281Sgonzo ccr &= ~DMA4_CCR_DST_ADDRESS_MODE(0x3); 1107239281Sgonzo ccr |= DMA4_CCR_DST_ADDRESS_MODE(dst_mode); 1108239281Sgonzo 1109239281Sgonzo sc->sc_channel[ch].reg_ccr = ccr; 1110239281Sgonzo 1111239281Sgonzo sc->sc_channel[ch].need_reg_write = 1; 1112239281Sgonzo 1113239281Sgonzo TI_SDMA_UNLOCK(sc); 1114239281Sgonzo 1115239281Sgonzo return 0; 1116239281Sgonzo} 1117239281Sgonzo 1118239281Sgonzo/** 1119239281Sgonzo * ti_sdma_probe - driver probe function 1120239281Sgonzo * @dev: dma device handle 1121239281Sgonzo * 1122239281Sgonzo * 1123239281Sgonzo * 1124239281Sgonzo * RETURNS: 1125239281Sgonzo * Always returns 0. 1126239281Sgonzo */ 1127239281Sgonzostatic int 1128239281Sgonzoti_sdma_probe(device_t dev) 1129239281Sgonzo{ 1130266152Sian 1131266152Sian if (!ofw_bus_status_okay(dev)) 1132266152Sian return (ENXIO); 1133266152Sian 1134239281Sgonzo if (!ofw_bus_is_compatible(dev, "ti,sdma")) 1135239281Sgonzo return (ENXIO); 1136239281Sgonzo 1137239281Sgonzo device_set_desc(dev, "TI sDMA Controller"); 1138239281Sgonzo return (0); 1139239281Sgonzo} 1140239281Sgonzo 1141239281Sgonzo/** 1142239281Sgonzo * ti_sdma_attach - driver attach function 1143239281Sgonzo * @dev: dma device handle 1144239281Sgonzo * 1145239281Sgonzo * Initialises memory mapping/pointers to the DMA register set and requests 1146239281Sgonzo * IRQs. This is effectively the setup function for the driver. 1147239281Sgonzo * 1148239281Sgonzo * RETURNS: 1149239281Sgonzo * 0 on success or a negative error code failure. 1150239281Sgonzo */ 1151239281Sgonzostatic int 1152239281Sgonzoti_sdma_attach(device_t dev) 1153239281Sgonzo{ 1154239281Sgonzo struct ti_sdma_softc *sc = device_get_softc(dev); 1155239281Sgonzo unsigned int timeout; 1156239281Sgonzo unsigned int i; 1157239281Sgonzo int rid; 1158239281Sgonzo void *ihl; 1159239281Sgonzo int err; 1160239281Sgonzo 1161239281Sgonzo /* Setup the basics */ 1162239281Sgonzo sc->sc_dev = dev; 1163239281Sgonzo 1164239281Sgonzo /* No channels active at the moment */ 1165239281Sgonzo sc->sc_active_channels = 0x00000000; 1166239281Sgonzo 1167239281Sgonzo /* Mutex to protect the shared data structures */ 1168239281Sgonzo TI_SDMA_LOCK_INIT(sc); 1169239281Sgonzo 1170239281Sgonzo /* Get the memory resource for the register mapping */ 1171239281Sgonzo rid = 0; 1172239281Sgonzo sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 1173239281Sgonzo if (sc->sc_mem_res == NULL) 1174239281Sgonzo panic("%s: Cannot map registers", device_get_name(dev)); 1175239281Sgonzo 1176239281Sgonzo /* Enable the interface and functional clocks */ 1177239281Sgonzo ti_prcm_clk_enable(SDMA_CLK); 1178239281Sgonzo 1179239281Sgonzo /* Read the sDMA revision register and sanity check it's known */ 1180239281Sgonzo sc->sc_hw_rev = ti_sdma_read_4(sc, DMA4_REVISION); 1181239281Sgonzo device_printf(dev, "sDMA revision %08x\n", sc->sc_hw_rev); 1182239281Sgonzo 1183239281Sgonzo if (!ti_sdma_is_omap4_rev(sc) && !ti_sdma_is_omap3_rev(sc)) { 1184239281Sgonzo device_printf(sc->sc_dev, "error - unknown sDMA H/W revision\n"); 1185239281Sgonzo return (EINVAL); 1186239281Sgonzo } 1187239281Sgonzo 1188239281Sgonzo /* Disable all interrupts */ 1189239281Sgonzo for (i = 0; i < NUM_DMA_IRQS; i++) { 1190239281Sgonzo ti_sdma_write_4(sc, DMA4_IRQENABLE_L(i), 0x00000000); 1191239281Sgonzo } 1192239281Sgonzo 1193239281Sgonzo /* Soft-reset is only supported on pre-OMAP44xx devices */ 1194239281Sgonzo if (ti_sdma_is_omap3_rev(sc)) { 1195239281Sgonzo 1196239281Sgonzo /* Soft-reset */ 1197239281Sgonzo ti_sdma_write_4(sc, DMA4_OCP_SYSCONFIG, 0x0002); 1198239281Sgonzo 1199239281Sgonzo /* Set the timeout to 100ms*/ 1200239281Sgonzo timeout = (hz < 10) ? 1 : ((100 * hz) / 1000); 1201239281Sgonzo 1202239281Sgonzo /* Wait for DMA reset to complete */ 1203239281Sgonzo while ((ti_sdma_read_4(sc, DMA4_SYSSTATUS) & 0x1) == 0x0) { 1204239281Sgonzo 1205239281Sgonzo /* Sleep for a tick */ 1206239281Sgonzo pause("DMARESET", 1); 1207239281Sgonzo 1208239281Sgonzo if (timeout-- == 0) { 1209239281Sgonzo device_printf(sc->sc_dev, "sDMA reset operation timed out\n"); 1210239281Sgonzo return (EINVAL); 1211239281Sgonzo } 1212239281Sgonzo } 1213239281Sgonzo } 1214239281Sgonzo 1215239281Sgonzo /* 1216239281Sgonzo * Install interrupt handlers for the for possible interrupts. Any channel 1217239281Sgonzo * can trip one of the four IRQs 1218239281Sgonzo */ 1219239281Sgonzo rid = 0; 1220239281Sgonzo sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 1221239281Sgonzo RF_ACTIVE | RF_SHAREABLE); 1222239281Sgonzo if (sc->sc_irq_res == NULL) 1223239281Sgonzo panic("Unable to setup the dma irq handler.\n"); 1224239281Sgonzo 1225239281Sgonzo err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 1226239281Sgonzo NULL, ti_sdma_intr, NULL, &ihl); 1227239281Sgonzo if (err) 1228239281Sgonzo panic("%s: Cannot register IRQ", device_get_name(dev)); 1229239281Sgonzo 1230239281Sgonzo /* Store the DMA structure globally ... this driver should never be unloaded */ 1231239281Sgonzo ti_sdma_sc = sc; 1232239281Sgonzo 1233239281Sgonzo return (0); 1234239281Sgonzo} 1235239281Sgonzo 1236239281Sgonzostatic device_method_t ti_sdma_methods[] = { 1237239281Sgonzo DEVMETHOD(device_probe, ti_sdma_probe), 1238239281Sgonzo DEVMETHOD(device_attach, ti_sdma_attach), 1239239281Sgonzo {0, 0}, 1240239281Sgonzo}; 1241239281Sgonzo 1242239281Sgonzostatic driver_t ti_sdma_driver = { 1243239281Sgonzo "ti_sdma", 1244239281Sgonzo ti_sdma_methods, 1245239281Sgonzo sizeof(struct ti_sdma_softc), 1246239281Sgonzo}; 1247239281Sgonzostatic devclass_t ti_sdma_devclass; 1248239281Sgonzo 1249239281SgonzoDRIVER_MODULE(ti_sdma, simplebus, ti_sdma_driver, ti_sdma_devclass, 0, 0); 1250239281SgonzoMODULE_DEPEND(ti_sdma, ti_prcm, 1, 1, 1); 1251