1e53470feSOleksandr Tymoshenko /*- 2e53470feSOleksandr Tymoshenko * Copyright (c) 2011 3e53470feSOleksandr Tymoshenko * Ben Gray <ben.r.gray@gmail.com>. 4e53470feSOleksandr Tymoshenko * All rights reserved. 5e53470feSOleksandr Tymoshenko * 6e53470feSOleksandr Tymoshenko * Redistribution and use in source and binary forms, with or without 7e53470feSOleksandr Tymoshenko * modification, are permitted provided that the following conditions 8e53470feSOleksandr Tymoshenko * are met: 9e53470feSOleksandr Tymoshenko * 1. Redistributions of source code must retain the above copyright 10e53470feSOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer. 11e53470feSOleksandr Tymoshenko * 2. Redistributions in binary form must reproduce the above copyright 12e53470feSOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer in the 13e53470feSOleksandr Tymoshenko * documentation and/or other materials provided with the distribution. 14e53470feSOleksandr Tymoshenko * 15e53470feSOleksandr Tymoshenko * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16e53470feSOleksandr Tymoshenko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17e53470feSOleksandr Tymoshenko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18e53470feSOleksandr Tymoshenko * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 19e53470feSOleksandr Tymoshenko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20e53470feSOleksandr Tymoshenko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21e53470feSOleksandr Tymoshenko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22e53470feSOleksandr Tymoshenko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23e53470feSOleksandr Tymoshenko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24e53470feSOleksandr Tymoshenko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25e53470feSOleksandr Tymoshenko * SUCH DAMAGE. 26e53470feSOleksandr Tymoshenko */ 27e53470feSOleksandr Tymoshenko 28e53470feSOleksandr Tymoshenko #include <sys/cdefs.h> 29e53470feSOleksandr Tymoshenko __FBSDID("$FreeBSD$"); 30e53470feSOleksandr Tymoshenko 31e53470feSOleksandr Tymoshenko #include <sys/param.h> 32e53470feSOleksandr Tymoshenko #include <sys/systm.h> 33e53470feSOleksandr Tymoshenko #include <sys/bus.h> 34e53470feSOleksandr Tymoshenko #include <sys/kernel.h> 35e53470feSOleksandr Tymoshenko #include <sys/lock.h> 36e53470feSOleksandr Tymoshenko #include <sys/interrupt.h> 37e53470feSOleksandr Tymoshenko #include <sys/module.h> 38e53470feSOleksandr Tymoshenko #include <sys/malloc.h> 39e53470feSOleksandr Tymoshenko #include <sys/mutex.h> 40e53470feSOleksandr Tymoshenko #include <sys/rman.h> 41e53470feSOleksandr Tymoshenko #include <sys/queue.h> 42e53470feSOleksandr Tymoshenko #include <sys/taskqueue.h> 43e53470feSOleksandr Tymoshenko #include <sys/timetc.h> 44e53470feSOleksandr Tymoshenko #include <machine/bus.h> 45e53470feSOleksandr Tymoshenko #include <machine/intr.h> 46e53470feSOleksandr Tymoshenko 47e53470feSOleksandr Tymoshenko #include <dev/fdt/fdt_common.h> 48e53470feSOleksandr Tymoshenko #include <dev/ofw/openfirm.h> 49e53470feSOleksandr Tymoshenko #include <dev/ofw/ofw_bus.h> 50e53470feSOleksandr Tymoshenko #include <dev/ofw/ofw_bus_subr.h> 51e53470feSOleksandr Tymoshenko 52e53470feSOleksandr Tymoshenko #include <arm/ti/ti_cpuid.h> 53e53470feSOleksandr Tymoshenko #include <arm/ti/ti_prcm.h> 54e53470feSOleksandr Tymoshenko #include <arm/ti/ti_sdma.h> 55e53470feSOleksandr Tymoshenko #include <arm/ti/ti_sdmareg.h> 56e53470feSOleksandr Tymoshenko 57e53470feSOleksandr Tymoshenko /** 58e53470feSOleksandr Tymoshenko * Kernel functions for using the DMA controller 59e53470feSOleksandr Tymoshenko * 60e53470feSOleksandr Tymoshenko * 61e53470feSOleksandr Tymoshenko * DMA TRANSFERS: 62e53470feSOleksandr Tymoshenko * A DMA transfer block consists of a number of frames (FN). Each frame 63e53470feSOleksandr Tymoshenko * consists of a number of elements, and each element can have a size of 8, 16, 64e53470feSOleksandr Tymoshenko * or 32 bits. 65e53470feSOleksandr Tymoshenko * 66e53470feSOleksandr Tymoshenko * OMAP44xx and newer chips support linked list (aka scatter gather) transfers, 67e53470feSOleksandr Tymoshenko * where a linked list of source/destination pairs can be placed in memory 68e53470feSOleksandr Tymoshenko * for the H/W to process. Earlier chips only allowed you to chain multiple 69e53470feSOleksandr Tymoshenko * channels together. However currently this linked list feature is not 70e53470feSOleksandr Tymoshenko * supported by the driver. 71e53470feSOleksandr Tymoshenko * 72e53470feSOleksandr Tymoshenko */ 73e53470feSOleksandr Tymoshenko 74e53470feSOleksandr Tymoshenko /** 75e53470feSOleksandr Tymoshenko * Data structure per DMA channel. 76e53470feSOleksandr Tymoshenko * 77e53470feSOleksandr Tymoshenko * 78e53470feSOleksandr Tymoshenko */ 79e53470feSOleksandr Tymoshenko struct ti_sdma_channel { 80e53470feSOleksandr Tymoshenko 81e53470feSOleksandr Tymoshenko /* 82e53470feSOleksandr Tymoshenko * The configuration registers for the given channel, these are modified 83e53470feSOleksandr Tymoshenko * by the set functions and only written to the actual registers when a 84e53470feSOleksandr Tymoshenko * transaction is started. 85e53470feSOleksandr Tymoshenko */ 86e53470feSOleksandr Tymoshenko uint32_t reg_csdp; 87e53470feSOleksandr Tymoshenko uint32_t reg_ccr; 88e53470feSOleksandr Tymoshenko uint32_t reg_cicr; 89e53470feSOleksandr Tymoshenko 90e53470feSOleksandr Tymoshenko /* Set when one of the configuration registers above change */ 91e53470feSOleksandr Tymoshenko uint32_t need_reg_write; 92e53470feSOleksandr Tymoshenko 93e53470feSOleksandr Tymoshenko /* Callback function used when an interrupt is tripped on the given channel */ 94e53470feSOleksandr Tymoshenko void (*callback)(unsigned int ch, uint32_t ch_status, void *data); 95e53470feSOleksandr Tymoshenko 96e53470feSOleksandr Tymoshenko /* Callback data passed in the callback ... duh */ 97e53470feSOleksandr Tymoshenko void* callback_data; 98e53470feSOleksandr Tymoshenko 99e53470feSOleksandr Tymoshenko }; 100e53470feSOleksandr Tymoshenko 101e53470feSOleksandr Tymoshenko /** 102e53470feSOleksandr Tymoshenko * DMA driver context, allocated and stored globally, this driver is not 103e53470feSOleksandr Tymoshenko * intetned to ever be unloaded (see ti_sdma_sc). 104e53470feSOleksandr Tymoshenko * 105e53470feSOleksandr Tymoshenko */ 106e53470feSOleksandr Tymoshenko struct ti_sdma_softc { 107e53470feSOleksandr Tymoshenko device_t sc_dev; 108e53470feSOleksandr Tymoshenko struct resource* sc_irq_res; 109e53470feSOleksandr Tymoshenko struct resource* sc_mem_res; 110e53470feSOleksandr Tymoshenko 111e53470feSOleksandr Tymoshenko /* 112e53470feSOleksandr Tymoshenko * I guess in theory we should have a mutex per DMA channel for register 113e53470feSOleksandr Tymoshenko * modifications. But since we know we are never going to be run on a SMP 114e53470feSOleksandr Tymoshenko * system, we can use just the single lock for all channels. 115e53470feSOleksandr Tymoshenko */ 116e53470feSOleksandr Tymoshenko struct mtx sc_mtx; 117e53470feSOleksandr Tymoshenko 118e53470feSOleksandr Tymoshenko /* Stores the H/W revision read from the registers */ 119e53470feSOleksandr Tymoshenko uint32_t sc_hw_rev; 120e53470feSOleksandr Tymoshenko 121e53470feSOleksandr Tymoshenko /* 122e53470feSOleksandr Tymoshenko * Bits in the sc_active_channels data field indicate if the channel has 123e53470feSOleksandr Tymoshenko * been activated. 124e53470feSOleksandr Tymoshenko */ 125e53470feSOleksandr Tymoshenko uint32_t sc_active_channels; 126e53470feSOleksandr Tymoshenko 127e53470feSOleksandr Tymoshenko struct ti_sdma_channel sc_channel[NUM_DMA_CHANNELS]; 128e53470feSOleksandr Tymoshenko 129e53470feSOleksandr Tymoshenko }; 130e53470feSOleksandr Tymoshenko 131e53470feSOleksandr Tymoshenko static struct ti_sdma_softc *ti_sdma_sc = NULL; 132e53470feSOleksandr Tymoshenko 133e53470feSOleksandr Tymoshenko /** 134e53470feSOleksandr Tymoshenko * Macros for driver mutex locking 135e53470feSOleksandr Tymoshenko */ 136e53470feSOleksandr Tymoshenko #define TI_SDMA_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx) 137e53470feSOleksandr Tymoshenko #define TI_SDMA_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx) 138e53470feSOleksandr Tymoshenko #define TI_SDMA_LOCK_INIT(_sc) \ 139e53470feSOleksandr Tymoshenko mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \ 140e53470feSOleksandr Tymoshenko "ti_sdma", MTX_SPIN) 141e53470feSOleksandr Tymoshenko #define TI_SDMA_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); 142e53470feSOleksandr Tymoshenko #define TI_SDMA_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); 143e53470feSOleksandr Tymoshenko #define TI_SDMA_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); 144e53470feSOleksandr Tymoshenko 145e53470feSOleksandr Tymoshenko /** 146e53470feSOleksandr Tymoshenko * Function prototypes 147e53470feSOleksandr Tymoshenko * 148e53470feSOleksandr Tymoshenko */ 149e53470feSOleksandr Tymoshenko static void ti_sdma_intr(void *); 150e53470feSOleksandr Tymoshenko 151e53470feSOleksandr Tymoshenko /** 152e53470feSOleksandr Tymoshenko * ti_sdma_read_4 - reads a 32-bit value from one of the DMA registers 153e53470feSOleksandr Tymoshenko * @sc: DMA device context 154e53470feSOleksandr Tymoshenko * @off: The offset of a register from the DMA register address range 155e53470feSOleksandr Tymoshenko * 156e53470feSOleksandr Tymoshenko * 157e53470feSOleksandr Tymoshenko * RETURNS: 158e53470feSOleksandr Tymoshenko * 32-bit value read from the register. 159e53470feSOleksandr Tymoshenko */ 160e53470feSOleksandr Tymoshenko static inline uint32_t 161e53470feSOleksandr Tymoshenko ti_sdma_read_4(struct ti_sdma_softc *sc, bus_size_t off) 162e53470feSOleksandr Tymoshenko { 163e53470feSOleksandr Tymoshenko return bus_read_4(sc->sc_mem_res, off); 164e53470feSOleksandr Tymoshenko } 165e53470feSOleksandr Tymoshenko 166e53470feSOleksandr Tymoshenko /** 167e53470feSOleksandr Tymoshenko * ti_sdma_write_4 - writes a 32-bit value to one of the DMA registers 168e53470feSOleksandr Tymoshenko * @sc: DMA device context 169e53470feSOleksandr Tymoshenko * @off: The offset of a register from the DMA register address range 170e53470feSOleksandr Tymoshenko * 171e53470feSOleksandr Tymoshenko * 172e53470feSOleksandr Tymoshenko * RETURNS: 173e53470feSOleksandr Tymoshenko * 32-bit value read from the register. 174e53470feSOleksandr Tymoshenko */ 175e53470feSOleksandr Tymoshenko static inline void 176e53470feSOleksandr Tymoshenko ti_sdma_write_4(struct ti_sdma_softc *sc, bus_size_t off, uint32_t val) 177e53470feSOleksandr Tymoshenko { 178e53470feSOleksandr Tymoshenko bus_write_4(sc->sc_mem_res, off, val); 179e53470feSOleksandr Tymoshenko } 180e53470feSOleksandr Tymoshenko 181e53470feSOleksandr Tymoshenko /** 182e53470feSOleksandr Tymoshenko * ti_sdma_is_omap3_rev - returns true if H/W is from OMAP3 series 183e53470feSOleksandr Tymoshenko * @sc: DMA device context 184e53470feSOleksandr Tymoshenko * 185e53470feSOleksandr Tymoshenko */ 186e53470feSOleksandr Tymoshenko static inline int 187e53470feSOleksandr Tymoshenko ti_sdma_is_omap3_rev(struct ti_sdma_softc *sc) 188e53470feSOleksandr Tymoshenko { 189e53470feSOleksandr Tymoshenko return (sc->sc_hw_rev == DMA4_OMAP3_REV); 190e53470feSOleksandr Tymoshenko } 191e53470feSOleksandr Tymoshenko 192e53470feSOleksandr Tymoshenko /** 193e53470feSOleksandr Tymoshenko * ti_sdma_is_omap4_rev - returns true if H/W is from OMAP4 series 194e53470feSOleksandr Tymoshenko * @sc: DMA device context 195e53470feSOleksandr Tymoshenko * 196e53470feSOleksandr Tymoshenko */ 197e53470feSOleksandr Tymoshenko static inline int 198e53470feSOleksandr Tymoshenko ti_sdma_is_omap4_rev(struct ti_sdma_softc *sc) 199e53470feSOleksandr Tymoshenko { 200e53470feSOleksandr Tymoshenko return (sc->sc_hw_rev == DMA4_OMAP4_REV); 201e53470feSOleksandr Tymoshenko } 202e53470feSOleksandr Tymoshenko 203e53470feSOleksandr Tymoshenko /** 204e53470feSOleksandr Tymoshenko * ti_sdma_intr - interrupt handler for all 4 DMA IRQs 205e53470feSOleksandr Tymoshenko * @arg: ignored 206e53470feSOleksandr Tymoshenko * 207e53470feSOleksandr Tymoshenko * Called when any of the four DMA IRQs are triggered. 208e53470feSOleksandr Tymoshenko * 209e53470feSOleksandr Tymoshenko * LOCKING: 210e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 211e53470feSOleksandr Tymoshenko * 212e53470feSOleksandr Tymoshenko * RETURNS: 213e53470feSOleksandr Tymoshenko * nothing 214e53470feSOleksandr Tymoshenko */ 215e53470feSOleksandr Tymoshenko static void 216e53470feSOleksandr Tymoshenko ti_sdma_intr(void *arg) 217e53470feSOleksandr Tymoshenko { 218e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 219e53470feSOleksandr Tymoshenko uint32_t intr; 220e53470feSOleksandr Tymoshenko uint32_t csr; 221e53470feSOleksandr Tymoshenko unsigned int ch, j; 222e53470feSOleksandr Tymoshenko struct ti_sdma_channel* channel; 223e53470feSOleksandr Tymoshenko 224e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 225e53470feSOleksandr Tymoshenko 226e53470feSOleksandr Tymoshenko for (j = 0; j < NUM_DMA_IRQS; j++) { 227e53470feSOleksandr Tymoshenko 228e53470feSOleksandr Tymoshenko /* Get the flag interrupts (enabled) */ 229e53470feSOleksandr Tymoshenko intr = ti_sdma_read_4(sc, DMA4_IRQSTATUS_L(j)); 230e53470feSOleksandr Tymoshenko intr &= ti_sdma_read_4(sc, DMA4_IRQENABLE_L(j)); 231e53470feSOleksandr Tymoshenko if (intr == 0x00000000) 232e53470feSOleksandr Tymoshenko continue; 233e53470feSOleksandr Tymoshenko 234e53470feSOleksandr Tymoshenko /* Loop through checking the status bits */ 235e53470feSOleksandr Tymoshenko for (ch = 0; ch < NUM_DMA_CHANNELS; ch++) { 236e53470feSOleksandr Tymoshenko if (intr & (1 << ch)) { 237e53470feSOleksandr Tymoshenko channel = &sc->sc_channel[ch]; 238e53470feSOleksandr Tymoshenko 239e53470feSOleksandr Tymoshenko /* Read the CSR regsiter and verify we don't have a spurious IRQ */ 240e53470feSOleksandr Tymoshenko csr = ti_sdma_read_4(sc, DMA4_CSR(ch)); 241e53470feSOleksandr Tymoshenko if (csr == 0) { 242e53470feSOleksandr Tymoshenko device_printf(sc->sc_dev, "Spurious DMA IRQ for channel " 243e53470feSOleksandr Tymoshenko "%d\n", ch); 244e53470feSOleksandr Tymoshenko continue; 245e53470feSOleksandr Tymoshenko } 246e53470feSOleksandr Tymoshenko 247e53470feSOleksandr Tymoshenko /* Sanity check this channel is active */ 248e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 249e53470feSOleksandr Tymoshenko device_printf(sc->sc_dev, "IRQ %d for a non-activated " 250e53470feSOleksandr Tymoshenko "channel %d\n", j, ch); 251e53470feSOleksandr Tymoshenko continue; 252e53470feSOleksandr Tymoshenko } 253e53470feSOleksandr Tymoshenko 254e53470feSOleksandr Tymoshenko /* Check the status error codes */ 255e53470feSOleksandr Tymoshenko if (csr & DMA4_CSR_DROP) 256e53470feSOleksandr Tymoshenko device_printf(sc->sc_dev, "Synchronization event drop " 257e53470feSOleksandr Tymoshenko "occurred during the transfer on channel %u\n", 258e53470feSOleksandr Tymoshenko ch); 259e53470feSOleksandr Tymoshenko if (csr & DMA4_CSR_SECURE_ERR) 260e53470feSOleksandr Tymoshenko device_printf(sc->sc_dev, "Secure transaction error event " 261e53470feSOleksandr Tymoshenko "on channel %u\n", ch); 262e53470feSOleksandr Tymoshenko if (csr & DMA4_CSR_MISALIGNED_ADRS_ERR) 263e53470feSOleksandr Tymoshenko device_printf(sc->sc_dev, "Misaligned address error event " 264e53470feSOleksandr Tymoshenko "on channel %u\n", ch); 265e53470feSOleksandr Tymoshenko if (csr & DMA4_CSR_TRANS_ERR) { 266e53470feSOleksandr Tymoshenko device_printf(sc->sc_dev, "Transaction error event on " 267e53470feSOleksandr Tymoshenko "channel %u\n", ch); 268e53470feSOleksandr Tymoshenko /* 269e53470feSOleksandr Tymoshenko * Apparently according to linux code, there is an errata 270e53470feSOleksandr Tymoshenko * that says the channel is not disabled upon this error. 271e53470feSOleksandr Tymoshenko * They explicitly disable the channel here .. since I 272e53470feSOleksandr Tymoshenko * haven't seen the errata, I'm going to ignore for now. 273e53470feSOleksandr Tymoshenko */ 274e53470feSOleksandr Tymoshenko } 275e53470feSOleksandr Tymoshenko 276e53470feSOleksandr Tymoshenko /* Clear the status flags for the IRQ */ 277e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK); 278e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch)); 279e53470feSOleksandr Tymoshenko 280e53470feSOleksandr Tymoshenko /* Call the callback for the given channel */ 281e53470feSOleksandr Tymoshenko if (channel->callback) 282e53470feSOleksandr Tymoshenko channel->callback(ch, csr, channel->callback_data); 283e53470feSOleksandr Tymoshenko } 284e53470feSOleksandr Tymoshenko } 285e53470feSOleksandr Tymoshenko } 286e53470feSOleksandr Tymoshenko 287e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 288e53470feSOleksandr Tymoshenko 289e53470feSOleksandr Tymoshenko return; 290e53470feSOleksandr Tymoshenko } 291e53470feSOleksandr Tymoshenko 292e53470feSOleksandr Tymoshenko /** 293e53470feSOleksandr Tymoshenko * ti_sdma_activate_channel - activates a DMA channel 294e53470feSOleksandr Tymoshenko * @ch: upon return contains the channel allocated 295e53470feSOleksandr Tymoshenko * @callback: a callback function to associate with the channel 296e53470feSOleksandr Tymoshenko * @data: optional data supplied when the callback is called 297e53470feSOleksandr Tymoshenko * 298e53470feSOleksandr Tymoshenko * Simply activates a channel be enabling and writing default values to the 299e53470feSOleksandr Tymoshenko * channel's register set. It doesn't start a transaction, just populates the 300e53470feSOleksandr Tymoshenko * internal data structures and sets defaults. 301e53470feSOleksandr Tymoshenko * 302e53470feSOleksandr Tymoshenko * Note this function doesn't enable interrupts, for that you need to call 303e53470feSOleksandr Tymoshenko * ti_sdma_enable_channel_irq(). If not using IRQ to detect the end of the 304e53470feSOleksandr Tymoshenko * transfer, you can use ti_sdma_status_poll() to detect a change in the 305e53470feSOleksandr Tymoshenko * status. 306e53470feSOleksandr Tymoshenko * 307e53470feSOleksandr Tymoshenko * A channel must be activated before any of the other DMA functions can be 308e53470feSOleksandr Tymoshenko * called on it. 309e53470feSOleksandr Tymoshenko * 310e53470feSOleksandr Tymoshenko * LOCKING: 311e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 312e53470feSOleksandr Tymoshenko * 313e53470feSOleksandr Tymoshenko * RETURNS: 314e53470feSOleksandr Tymoshenko * 0 on success, otherwise an error code 315e53470feSOleksandr Tymoshenko */ 316e53470feSOleksandr Tymoshenko int 317e53470feSOleksandr Tymoshenko ti_sdma_activate_channel(unsigned int *ch, 318e53470feSOleksandr Tymoshenko void (*callback)(unsigned int ch, uint32_t status, void *data), 319e53470feSOleksandr Tymoshenko void *data) 320e53470feSOleksandr Tymoshenko { 321e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 322e53470feSOleksandr Tymoshenko struct ti_sdma_channel *channel = NULL; 323e53470feSOleksandr Tymoshenko uint32_t addr; 324e53470feSOleksandr Tymoshenko unsigned int i; 325e53470feSOleksandr Tymoshenko 326e53470feSOleksandr Tymoshenko /* Sanity check */ 327e53470feSOleksandr Tymoshenko if (sc == NULL) 328e53470feSOleksandr Tymoshenko return (ENOMEM); 329e53470feSOleksandr Tymoshenko 330e53470feSOleksandr Tymoshenko if (ch == NULL) 331e53470feSOleksandr Tymoshenko return (EINVAL); 332e53470feSOleksandr Tymoshenko 333e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 334e53470feSOleksandr Tymoshenko 335e53470feSOleksandr Tymoshenko /* Check to see if all channels are in use */ 336e53470feSOleksandr Tymoshenko if (sc->sc_active_channels == 0xffffffff) { 337e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 338e53470feSOleksandr Tymoshenko return (ENOMEM); 339e53470feSOleksandr Tymoshenko } 340e53470feSOleksandr Tymoshenko 341e53470feSOleksandr Tymoshenko /* Find the first non-active channel */ 342e53470feSOleksandr Tymoshenko for (i = 0; i < NUM_DMA_CHANNELS; i++) { 343e53470feSOleksandr Tymoshenko if (!(sc->sc_active_channels & (0x1 << i))) { 344e53470feSOleksandr Tymoshenko sc->sc_active_channels |= (0x1 << i); 345e53470feSOleksandr Tymoshenko *ch = i; 346e53470feSOleksandr Tymoshenko break; 347e53470feSOleksandr Tymoshenko } 348e53470feSOleksandr Tymoshenko } 349e53470feSOleksandr Tymoshenko 350e53470feSOleksandr Tymoshenko /* Get the channel struct and populate the fields */ 351e53470feSOleksandr Tymoshenko channel = &sc->sc_channel[*ch]; 352e53470feSOleksandr Tymoshenko 353e53470feSOleksandr Tymoshenko channel->callback = callback; 354e53470feSOleksandr Tymoshenko channel->callback_data = data; 355e53470feSOleksandr Tymoshenko 356e53470feSOleksandr Tymoshenko channel->need_reg_write = 1; 357e53470feSOleksandr Tymoshenko 358e53470feSOleksandr Tymoshenko /* Set the default configuration for the DMA channel */ 359e53470feSOleksandr Tymoshenko channel->reg_csdp = DMA4_CSDP_DATA_TYPE(0x2) 360e53470feSOleksandr Tymoshenko | DMA4_CSDP_SRC_BURST_MODE(0) 361e53470feSOleksandr Tymoshenko | DMA4_CSDP_DST_BURST_MODE(0) 362e53470feSOleksandr Tymoshenko | DMA4_CSDP_SRC_ENDIANISM(0) 363e53470feSOleksandr Tymoshenko | DMA4_CSDP_DST_ENDIANISM(0) 364e53470feSOleksandr Tymoshenko | DMA4_CSDP_WRITE_MODE(0) 365e53470feSOleksandr Tymoshenko | DMA4_CSDP_SRC_PACKED(0) 366e53470feSOleksandr Tymoshenko | DMA4_CSDP_DST_PACKED(0); 367e53470feSOleksandr Tymoshenko 368e53470feSOleksandr Tymoshenko channel->reg_ccr = DMA4_CCR_DST_ADDRESS_MODE(1) 369e53470feSOleksandr Tymoshenko | DMA4_CCR_SRC_ADDRESS_MODE(1) 370e53470feSOleksandr Tymoshenko | DMA4_CCR_READ_PRIORITY(0) 371e53470feSOleksandr Tymoshenko | DMA4_CCR_WRITE_PRIORITY(0) 372e53470feSOleksandr Tymoshenko | DMA4_CCR_SYNC_TRIGGER(0) 373e53470feSOleksandr Tymoshenko | DMA4_CCR_FRAME_SYNC(0) 374e53470feSOleksandr Tymoshenko | DMA4_CCR_BLOCK_SYNC(0); 375e53470feSOleksandr Tymoshenko 376e53470feSOleksandr Tymoshenko channel->reg_cicr = DMA4_CICR_TRANS_ERR_IE 377e53470feSOleksandr Tymoshenko | DMA4_CICR_SECURE_ERR_IE 378e53470feSOleksandr Tymoshenko | DMA4_CICR_SUPERVISOR_ERR_IE 379e53470feSOleksandr Tymoshenko | DMA4_CICR_MISALIGNED_ADRS_ERR_IE; 380e53470feSOleksandr Tymoshenko 381e53470feSOleksandr Tymoshenko /* Clear all the channel registers, this should abort any transaction */ 382e53470feSOleksandr Tymoshenko for (addr = DMA4_CCR(*ch); addr <= DMA4_COLOR(*ch); addr += 4) 383e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, addr, 0x00000000); 384e53470feSOleksandr Tymoshenko 385e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 386e53470feSOleksandr Tymoshenko 387e53470feSOleksandr Tymoshenko return 0; 388e53470feSOleksandr Tymoshenko } 389e53470feSOleksandr Tymoshenko 390e53470feSOleksandr Tymoshenko /** 391e53470feSOleksandr Tymoshenko * ti_sdma_deactivate_channel - deactivates a channel 392e53470feSOleksandr Tymoshenko * @ch: the channel to deactivate 393e53470feSOleksandr Tymoshenko * 394e53470feSOleksandr Tymoshenko * 395e53470feSOleksandr Tymoshenko * 396e53470feSOleksandr Tymoshenko * LOCKING: 397e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 398e53470feSOleksandr Tymoshenko * 399e53470feSOleksandr Tymoshenko * RETURNS: 400e53470feSOleksandr Tymoshenko * EH_HANDLED or EH_NOT_HANDLED 401e53470feSOleksandr Tymoshenko */ 402e53470feSOleksandr Tymoshenko int 403e53470feSOleksandr Tymoshenko ti_sdma_deactivate_channel(unsigned int ch) 404e53470feSOleksandr Tymoshenko { 405e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 406e53470feSOleksandr Tymoshenko unsigned int j; 407e53470feSOleksandr Tymoshenko unsigned int addr; 408e53470feSOleksandr Tymoshenko 409e53470feSOleksandr Tymoshenko /* Sanity check */ 410e53470feSOleksandr Tymoshenko if (sc == NULL) 411e53470feSOleksandr Tymoshenko return (ENOMEM); 412e53470feSOleksandr Tymoshenko 413e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 414e53470feSOleksandr Tymoshenko 415e53470feSOleksandr Tymoshenko /* First check if the channel is currently active */ 416e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 417e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 418e53470feSOleksandr Tymoshenko return (EBUSY); 419e53470feSOleksandr Tymoshenko } 420e53470feSOleksandr Tymoshenko 421e53470feSOleksandr Tymoshenko /* Mark the channel as inactive */ 422e53470feSOleksandr Tymoshenko sc->sc_active_channels &= ~(1 << ch); 423e53470feSOleksandr Tymoshenko 424e53470feSOleksandr Tymoshenko /* Disable all DMA interrupts for the channel. */ 425e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CICR(ch), 0); 426e53470feSOleksandr Tymoshenko 427e53470feSOleksandr Tymoshenko /* Make sure the DMA transfer is stopped. */ 428e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CCR(ch), 0); 429e53470feSOleksandr Tymoshenko 430e53470feSOleksandr Tymoshenko /* Clear the CSR register and IRQ status register */ 431e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK); 432e53470feSOleksandr Tymoshenko for (j = 0; j < NUM_DMA_IRQS; j++) { 433e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch)); 434e53470feSOleksandr Tymoshenko } 435e53470feSOleksandr Tymoshenko 436e53470feSOleksandr Tymoshenko /* Clear all the channel registers, this should abort any transaction */ 437e53470feSOleksandr Tymoshenko for (addr = DMA4_CCR(ch); addr <= DMA4_COLOR(ch); addr += 4) 438e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, addr, 0x00000000); 439e53470feSOleksandr Tymoshenko 440e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 441e53470feSOleksandr Tymoshenko 442e53470feSOleksandr Tymoshenko return 0; 443e53470feSOleksandr Tymoshenko } 444e53470feSOleksandr Tymoshenko 445e53470feSOleksandr Tymoshenko /** 446e53470feSOleksandr Tymoshenko * ti_sdma_disable_channel_irq - disables IRQ's on the given channel 447e53470feSOleksandr Tymoshenko * @ch: the channel to disable IRQ's on 448e53470feSOleksandr Tymoshenko * 449*255eff3bSPedro F. Giffuni * Disable interrupt generation for the given channel. 450e53470feSOleksandr Tymoshenko * 451e53470feSOleksandr Tymoshenko * LOCKING: 452e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 453e53470feSOleksandr Tymoshenko * 454e53470feSOleksandr Tymoshenko * RETURNS: 455e53470feSOleksandr Tymoshenko * EH_HANDLED or EH_NOT_HANDLED 456e53470feSOleksandr Tymoshenko */ 457e53470feSOleksandr Tymoshenko int 458e53470feSOleksandr Tymoshenko ti_sdma_disable_channel_irq(unsigned int ch) 459e53470feSOleksandr Tymoshenko { 460e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 461e53470feSOleksandr Tymoshenko uint32_t irq_enable; 462e53470feSOleksandr Tymoshenko unsigned int j; 463e53470feSOleksandr Tymoshenko 464e53470feSOleksandr Tymoshenko /* Sanity check */ 465e53470feSOleksandr Tymoshenko if (sc == NULL) 466e53470feSOleksandr Tymoshenko return (ENOMEM); 467e53470feSOleksandr Tymoshenko 468e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 469e53470feSOleksandr Tymoshenko 470e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 471e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 472e53470feSOleksandr Tymoshenko return (EINVAL); 473e53470feSOleksandr Tymoshenko } 474e53470feSOleksandr Tymoshenko 475e53470feSOleksandr Tymoshenko /* Disable all the individual error conditions */ 476e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_cicr = 0x0000; 477e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CICR(ch), 0x0000); 478e53470feSOleksandr Tymoshenko 479e53470feSOleksandr Tymoshenko /* Disable the channel interrupt enable */ 480e53470feSOleksandr Tymoshenko for (j = 0; j < NUM_DMA_IRQS; j++) { 481e53470feSOleksandr Tymoshenko irq_enable = ti_sdma_read_4(sc, DMA4_IRQENABLE_L(j)); 482e53470feSOleksandr Tymoshenko irq_enable &= ~(1 << ch); 483e53470feSOleksandr Tymoshenko 484e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_IRQENABLE_L(j), irq_enable); 485e53470feSOleksandr Tymoshenko } 486e53470feSOleksandr Tymoshenko 487e53470feSOleksandr Tymoshenko /* Indicate the registers need to be rewritten on the next transaction */ 488e53470feSOleksandr Tymoshenko sc->sc_channel[ch].need_reg_write = 1; 489e53470feSOleksandr Tymoshenko 490e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 491e53470feSOleksandr Tymoshenko 492e53470feSOleksandr Tymoshenko return (0); 493e53470feSOleksandr Tymoshenko } 494e53470feSOleksandr Tymoshenko 495e53470feSOleksandr Tymoshenko /** 496e53470feSOleksandr Tymoshenko * ti_sdma_disable_channel_irq - enables IRQ's on the given channel 497e53470feSOleksandr Tymoshenko * @ch: the channel to enable IRQ's on 498e53470feSOleksandr Tymoshenko * @flags: bitmask of interrupt types to enable 499e53470feSOleksandr Tymoshenko * 500e53470feSOleksandr Tymoshenko * Flags can be a bitmask of the following options: 501e53470feSOleksandr Tymoshenko * DMA_IRQ_FLAG_DROP 502e53470feSOleksandr Tymoshenko * DMA_IRQ_FLAG_HALF_FRAME_COMPL 503e53470feSOleksandr Tymoshenko * DMA_IRQ_FLAG_FRAME_COMPL 504e53470feSOleksandr Tymoshenko * DMA_IRQ_FLAG_START_LAST_FRAME 505e53470feSOleksandr Tymoshenko * DMA_IRQ_FLAG_BLOCK_COMPL 506e53470feSOleksandr Tymoshenko * DMA_IRQ_FLAG_ENDOF_PKT 507e53470feSOleksandr Tymoshenko * DMA_IRQ_FLAG_DRAIN 508e53470feSOleksandr Tymoshenko * 509e53470feSOleksandr Tymoshenko * 510e53470feSOleksandr Tymoshenko * LOCKING: 511e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 512e53470feSOleksandr Tymoshenko * 513e53470feSOleksandr Tymoshenko * RETURNS: 514e53470feSOleksandr Tymoshenko * EH_HANDLED or EH_NOT_HANDLED 515e53470feSOleksandr Tymoshenko */ 516e53470feSOleksandr Tymoshenko int 517e53470feSOleksandr Tymoshenko ti_sdma_enable_channel_irq(unsigned int ch, uint32_t flags) 518e53470feSOleksandr Tymoshenko { 519e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 520e53470feSOleksandr Tymoshenko uint32_t irq_enable; 521e53470feSOleksandr Tymoshenko 522e53470feSOleksandr Tymoshenko /* Sanity check */ 523e53470feSOleksandr Tymoshenko if (sc == NULL) 524e53470feSOleksandr Tymoshenko return (ENOMEM); 525e53470feSOleksandr Tymoshenko 526e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 527e53470feSOleksandr Tymoshenko 528e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 529e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 530e53470feSOleksandr Tymoshenko return (EINVAL); 531e53470feSOleksandr Tymoshenko } 532e53470feSOleksandr Tymoshenko 533e53470feSOleksandr Tymoshenko /* Always enable the error interrupts if we have interrupts enabled */ 534e53470feSOleksandr Tymoshenko flags |= DMA4_CICR_TRANS_ERR_IE | DMA4_CICR_SECURE_ERR_IE | 535e53470feSOleksandr Tymoshenko DMA4_CICR_SUPERVISOR_ERR_IE | DMA4_CICR_MISALIGNED_ADRS_ERR_IE; 536e53470feSOleksandr Tymoshenko 537e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_cicr = flags; 538e53470feSOleksandr Tymoshenko 539e53470feSOleksandr Tymoshenko /* Write the values to the register */ 540e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CICR(ch), flags); 541e53470feSOleksandr Tymoshenko 542e53470feSOleksandr Tymoshenko /* Enable the channel interrupt enable */ 543e53470feSOleksandr Tymoshenko irq_enable = ti_sdma_read_4(sc, DMA4_IRQENABLE_L(0)); 544e53470feSOleksandr Tymoshenko irq_enable |= (1 << ch); 545e53470feSOleksandr Tymoshenko 546e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_IRQENABLE_L(0), irq_enable); 547e53470feSOleksandr Tymoshenko 548e53470feSOleksandr Tymoshenko /* Indicate the registers need to be rewritten on the next transaction */ 549e53470feSOleksandr Tymoshenko sc->sc_channel[ch].need_reg_write = 1; 550e53470feSOleksandr Tymoshenko 551e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 552e53470feSOleksandr Tymoshenko 553e53470feSOleksandr Tymoshenko return (0); 554e53470feSOleksandr Tymoshenko } 555e53470feSOleksandr Tymoshenko 556e53470feSOleksandr Tymoshenko /** 557e53470feSOleksandr Tymoshenko * ti_sdma_get_channel_status - returns the status of a given channel 558e53470feSOleksandr Tymoshenko * @ch: the channel number to get the status of 559e53470feSOleksandr Tymoshenko * @status: upon return will contain the status bitmask, see below for possible 560e53470feSOleksandr Tymoshenko * values. 561e53470feSOleksandr Tymoshenko * 562e53470feSOleksandr Tymoshenko * DMA_STATUS_DROP 563e53470feSOleksandr Tymoshenko * DMA_STATUS_HALF 564e53470feSOleksandr Tymoshenko * DMA_STATUS_FRAME 565e53470feSOleksandr Tymoshenko * DMA_STATUS_LAST 566e53470feSOleksandr Tymoshenko * DMA_STATUS_BLOCK 567e53470feSOleksandr Tymoshenko * DMA_STATUS_SYNC 568e53470feSOleksandr Tymoshenko * DMA_STATUS_PKT 569e53470feSOleksandr Tymoshenko * DMA_STATUS_TRANS_ERR 570e53470feSOleksandr Tymoshenko * DMA_STATUS_SECURE_ERR 571e53470feSOleksandr Tymoshenko * DMA_STATUS_SUPERVISOR_ERR 572e53470feSOleksandr Tymoshenko * DMA_STATUS_MISALIGNED_ADRS_ERR 573e53470feSOleksandr Tymoshenko * DMA_STATUS_DRAIN_END 574e53470feSOleksandr Tymoshenko * 575e53470feSOleksandr Tymoshenko * 576e53470feSOleksandr Tymoshenko * LOCKING: 577e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 578e53470feSOleksandr Tymoshenko * 579e53470feSOleksandr Tymoshenko * RETURNS: 580e53470feSOleksandr Tymoshenko * EH_HANDLED or EH_NOT_HANDLED 581e53470feSOleksandr Tymoshenko */ 582e53470feSOleksandr Tymoshenko int 583e53470feSOleksandr Tymoshenko ti_sdma_get_channel_status(unsigned int ch, uint32_t *status) 584e53470feSOleksandr Tymoshenko { 585e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 586e53470feSOleksandr Tymoshenko uint32_t csr; 587e53470feSOleksandr Tymoshenko 588e53470feSOleksandr Tymoshenko /* Sanity check */ 589e53470feSOleksandr Tymoshenko if (sc == NULL) 590e53470feSOleksandr Tymoshenko return (ENOMEM); 591e53470feSOleksandr Tymoshenko 592e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 593e53470feSOleksandr Tymoshenko 594e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 595e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 596e53470feSOleksandr Tymoshenko return (EINVAL); 597e53470feSOleksandr Tymoshenko } 598e53470feSOleksandr Tymoshenko 599e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 600e53470feSOleksandr Tymoshenko 601e53470feSOleksandr Tymoshenko csr = ti_sdma_read_4(sc, DMA4_CSR(ch)); 602e53470feSOleksandr Tymoshenko 603e53470feSOleksandr Tymoshenko if (status != NULL) 604e53470feSOleksandr Tymoshenko *status = csr; 605e53470feSOleksandr Tymoshenko 606e53470feSOleksandr Tymoshenko return (0); 607e53470feSOleksandr Tymoshenko } 608e53470feSOleksandr Tymoshenko 609e53470feSOleksandr Tymoshenko /** 610e53470feSOleksandr Tymoshenko * ti_sdma_start_xfer - starts a DMA transfer 611*255eff3bSPedro F. Giffuni * @ch: the channel number to set the endianness of 612e53470feSOleksandr Tymoshenko * @src_paddr: the source phsyical address 613e53470feSOleksandr Tymoshenko * @dst_paddr: the destination phsyical address 614e53470feSOleksandr Tymoshenko * @frmcnt: the number of frames per block 615e53470feSOleksandr Tymoshenko * @elmcnt: the number of elements in a frame, an element is either an 8, 16 616e53470feSOleksandr Tymoshenko * or 32-bit value as defined by ti_sdma_set_xfer_burst() 617e53470feSOleksandr Tymoshenko * 618e53470feSOleksandr Tymoshenko * 619e53470feSOleksandr Tymoshenko * LOCKING: 620e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 621e53470feSOleksandr Tymoshenko * 622e53470feSOleksandr Tymoshenko * RETURNS: 623e53470feSOleksandr Tymoshenko * EH_HANDLED or EH_NOT_HANDLED 624e53470feSOleksandr Tymoshenko */ 625e53470feSOleksandr Tymoshenko int 626e53470feSOleksandr Tymoshenko ti_sdma_start_xfer(unsigned int ch, unsigned int src_paddr, 627e53470feSOleksandr Tymoshenko unsigned long dst_paddr, 628e53470feSOleksandr Tymoshenko unsigned int frmcnt, unsigned int elmcnt) 629e53470feSOleksandr Tymoshenko { 630e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 631e53470feSOleksandr Tymoshenko struct ti_sdma_channel *channel; 632e53470feSOleksandr Tymoshenko uint32_t ccr; 633e53470feSOleksandr Tymoshenko 634e53470feSOleksandr Tymoshenko /* Sanity check */ 635e53470feSOleksandr Tymoshenko if (sc == NULL) 636e53470feSOleksandr Tymoshenko return (ENOMEM); 637e53470feSOleksandr Tymoshenko 638e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 639e53470feSOleksandr Tymoshenko 640e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 641e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 642e53470feSOleksandr Tymoshenko return (EINVAL); 643e53470feSOleksandr Tymoshenko } 644e53470feSOleksandr Tymoshenko 645e53470feSOleksandr Tymoshenko channel = &sc->sc_channel[ch]; 646e53470feSOleksandr Tymoshenko 647e53470feSOleksandr Tymoshenko /* a) Write the CSDP register */ 648e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CSDP(ch), 649e53470feSOleksandr Tymoshenko channel->reg_csdp | DMA4_CSDP_WRITE_MODE(1)); 650e53470feSOleksandr Tymoshenko 651e53470feSOleksandr Tymoshenko /* b) Set the number of element per frame CEN[23:0] */ 652e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CEN(ch), elmcnt); 653e53470feSOleksandr Tymoshenko 654e53470feSOleksandr Tymoshenko /* c) Set the number of frame per block CFN[15:0] */ 655e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CFN(ch), frmcnt); 656e53470feSOleksandr Tymoshenko 657e53470feSOleksandr Tymoshenko /* d) Set the Source/dest start address index CSSA[31:0]/CDSA[31:0] */ 658e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CSSA(ch), src_paddr); 659e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CDSA(ch), dst_paddr); 660e53470feSOleksandr Tymoshenko 661e53470feSOleksandr Tymoshenko /* e) Write the CCR register */ 662e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CCR(ch), channel->reg_ccr); 663e53470feSOleksandr Tymoshenko 664e53470feSOleksandr Tymoshenko /* f) - Set the source element index increment CSEI[15:0] */ 665e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CSE(ch), 0x0001); 666e53470feSOleksandr Tymoshenko 667e53470feSOleksandr Tymoshenko /* - Set the source frame index increment CSFI[15:0] */ 668e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CSF(ch), 0x0001); 669e53470feSOleksandr Tymoshenko 670e53470feSOleksandr Tymoshenko /* - Set the destination element index increment CDEI[15:0]*/ 671e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CDE(ch), 0x0001); 672e53470feSOleksandr Tymoshenko 673e53470feSOleksandr Tymoshenko /* - Set the destination frame index increment CDFI[31:0] */ 674e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CDF(ch), 0x0001); 675e53470feSOleksandr Tymoshenko 676e53470feSOleksandr Tymoshenko /* Clear the status register */ 677e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CSR(ch), 0x1FFE); 678e53470feSOleksandr Tymoshenko 679e53470feSOleksandr Tymoshenko /* Write the start-bit and away we go */ 680e53470feSOleksandr Tymoshenko ccr = ti_sdma_read_4(sc, DMA4_CCR(ch)); 681e53470feSOleksandr Tymoshenko ccr |= (1 << 7); 682e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CCR(ch), ccr); 683e53470feSOleksandr Tymoshenko 684e53470feSOleksandr Tymoshenko /* Clear the reg write flag */ 685e53470feSOleksandr Tymoshenko channel->need_reg_write = 0; 686e53470feSOleksandr Tymoshenko 687e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 688e53470feSOleksandr Tymoshenko 689e53470feSOleksandr Tymoshenko return (0); 690e53470feSOleksandr Tymoshenko } 691e53470feSOleksandr Tymoshenko 692e53470feSOleksandr Tymoshenko /** 693e53470feSOleksandr Tymoshenko * ti_sdma_start_xfer_packet - starts a packet DMA transfer 694e53470feSOleksandr Tymoshenko * @ch: the channel number to use for the transfer 695e53470feSOleksandr Tymoshenko * @src_paddr: the source physical address 696e53470feSOleksandr Tymoshenko * @dst_paddr: the destination physical address 697e53470feSOleksandr Tymoshenko * @frmcnt: the number of frames to transfer 698e53470feSOleksandr Tymoshenko * @elmcnt: the number of elements in a frame, an element is either an 8, 16 699e53470feSOleksandr Tymoshenko * or 32-bit value as defined by ti_sdma_set_xfer_burst() 700e53470feSOleksandr Tymoshenko * @pktsize: the number of elements in each transfer packet 701e53470feSOleksandr Tymoshenko * 702e53470feSOleksandr Tymoshenko * The @frmcnt and @elmcnt define the overall number of bytes to transfer, 703e53470feSOleksandr Tymoshenko * typically @frmcnt is 1 and @elmcnt contains the total number of elements. 704e53470feSOleksandr Tymoshenko * @pktsize is the size of each individual packet, there might be multiple 705e53470feSOleksandr Tymoshenko * packets per transfer. i.e. for the following with element size of 32-bits 706e53470feSOleksandr Tymoshenko * 707e53470feSOleksandr Tymoshenko * frmcnt = 1, elmcnt = 512, pktsize = 128 708e53470feSOleksandr Tymoshenko * 709e53470feSOleksandr Tymoshenko * Total transfer bytes = 1 * 512 = 512 elements or 2048 bytes 710*255eff3bSPedro F. Giffuni * Packets transferred = 128 / 512 = 4 711e53470feSOleksandr Tymoshenko * 712e53470feSOleksandr Tymoshenko * 713e53470feSOleksandr Tymoshenko * LOCKING: 714e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 715e53470feSOleksandr Tymoshenko * 716e53470feSOleksandr Tymoshenko * RETURNS: 717e53470feSOleksandr Tymoshenko * EH_HANDLED or EH_NOT_HANDLED 718e53470feSOleksandr Tymoshenko */ 719e53470feSOleksandr Tymoshenko int 720e53470feSOleksandr Tymoshenko ti_sdma_start_xfer_packet(unsigned int ch, unsigned int src_paddr, 721e53470feSOleksandr Tymoshenko unsigned long dst_paddr, unsigned int frmcnt, 722e53470feSOleksandr Tymoshenko unsigned int elmcnt, unsigned int pktsize) 723e53470feSOleksandr Tymoshenko { 724e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 725e53470feSOleksandr Tymoshenko struct ti_sdma_channel *channel; 726e53470feSOleksandr Tymoshenko uint32_t ccr; 727e53470feSOleksandr Tymoshenko 728e53470feSOleksandr Tymoshenko /* Sanity check */ 729e53470feSOleksandr Tymoshenko if (sc == NULL) 730e53470feSOleksandr Tymoshenko return (ENOMEM); 731e53470feSOleksandr Tymoshenko 732e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 733e53470feSOleksandr Tymoshenko 734e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 735e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 736e53470feSOleksandr Tymoshenko return (EINVAL); 737e53470feSOleksandr Tymoshenko } 738e53470feSOleksandr Tymoshenko 739e53470feSOleksandr Tymoshenko channel = &sc->sc_channel[ch]; 740e53470feSOleksandr Tymoshenko 741e53470feSOleksandr Tymoshenko /* a) Write the CSDP register */ 742e53470feSOleksandr Tymoshenko if (channel->need_reg_write) 743e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CSDP(ch), 744e53470feSOleksandr Tymoshenko channel->reg_csdp | DMA4_CSDP_WRITE_MODE(1)); 745e53470feSOleksandr Tymoshenko 746e53470feSOleksandr Tymoshenko /* b) Set the number of elements to transfer CEN[23:0] */ 747e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CEN(ch), elmcnt); 748e53470feSOleksandr Tymoshenko 749e53470feSOleksandr Tymoshenko /* c) Set the number of frames to transfer CFN[15:0] */ 750e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CFN(ch), frmcnt); 751e53470feSOleksandr Tymoshenko 752e53470feSOleksandr Tymoshenko /* d) Set the Source/dest start address index CSSA[31:0]/CDSA[31:0] */ 753e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CSSA(ch), src_paddr); 754e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CDSA(ch), dst_paddr); 755e53470feSOleksandr Tymoshenko 756e53470feSOleksandr Tymoshenko /* e) Write the CCR register */ 757e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CCR(ch), 758e53470feSOleksandr Tymoshenko channel->reg_ccr | DMA4_CCR_PACKET_TRANS); 759e53470feSOleksandr Tymoshenko 760e53470feSOleksandr Tymoshenko /* f) - Set the source element index increment CSEI[15:0] */ 761e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CSE(ch), 0x0001); 762e53470feSOleksandr Tymoshenko 763e53470feSOleksandr Tymoshenko /* - Set the packet size, this is dependent on the sync source */ 764e53470feSOleksandr Tymoshenko if (channel->reg_ccr & DMA4_CCR_SEL_SRC_DST_SYNC(1)) 765e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CSF(ch), pktsize); 766e53470feSOleksandr Tymoshenko else 767e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CDF(ch), pktsize); 768e53470feSOleksandr Tymoshenko 769e53470feSOleksandr Tymoshenko /* - Set the destination frame index increment CDFI[31:0] */ 770e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CDE(ch), 0x0001); 771e53470feSOleksandr Tymoshenko 772e53470feSOleksandr Tymoshenko /* Clear the status register */ 773e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CSR(ch), 0x1FFE); 774e53470feSOleksandr Tymoshenko 775e53470feSOleksandr Tymoshenko /* Write the start-bit and away we go */ 776e53470feSOleksandr Tymoshenko ccr = ti_sdma_read_4(sc, DMA4_CCR(ch)); 777e53470feSOleksandr Tymoshenko ccr |= (1 << 7); 778e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CCR(ch), ccr); 779e53470feSOleksandr Tymoshenko 780e53470feSOleksandr Tymoshenko /* Clear the reg write flag */ 781e53470feSOleksandr Tymoshenko channel->need_reg_write = 0; 782e53470feSOleksandr Tymoshenko 783e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 784e53470feSOleksandr Tymoshenko 785e53470feSOleksandr Tymoshenko return (0); 786e53470feSOleksandr Tymoshenko } 787e53470feSOleksandr Tymoshenko 788e53470feSOleksandr Tymoshenko /** 789e53470feSOleksandr Tymoshenko * ti_sdma_stop_xfer - stops any currently active transfers 790*255eff3bSPedro F. Giffuni * @ch: the channel number to set the endianness of 791e53470feSOleksandr Tymoshenko * 792e53470feSOleksandr Tymoshenko * This function call is effectively a NOP if no transaction is in progress. 793e53470feSOleksandr Tymoshenko * 794e53470feSOleksandr Tymoshenko * LOCKING: 795e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 796e53470feSOleksandr Tymoshenko * 797e53470feSOleksandr Tymoshenko * RETURNS: 798e53470feSOleksandr Tymoshenko * EH_HANDLED or EH_NOT_HANDLED 799e53470feSOleksandr Tymoshenko */ 800e53470feSOleksandr Tymoshenko int 801e53470feSOleksandr Tymoshenko ti_sdma_stop_xfer(unsigned int ch) 802e53470feSOleksandr Tymoshenko { 803e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 804e53470feSOleksandr Tymoshenko unsigned int j; 805e53470feSOleksandr Tymoshenko 806e53470feSOleksandr Tymoshenko /* Sanity check */ 807e53470feSOleksandr Tymoshenko if (sc == NULL) 808e53470feSOleksandr Tymoshenko return (ENOMEM); 809e53470feSOleksandr Tymoshenko 810e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 811e53470feSOleksandr Tymoshenko 812e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 813e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 814e53470feSOleksandr Tymoshenko return (EINVAL); 815e53470feSOleksandr Tymoshenko } 816e53470feSOleksandr Tymoshenko 817e53470feSOleksandr Tymoshenko /* Disable all DMA interrupts for the channel. */ 818e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CICR(ch), 0); 819e53470feSOleksandr Tymoshenko 820e53470feSOleksandr Tymoshenko /* Make sure the DMA transfer is stopped. */ 821e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CCR(ch), 0); 822e53470feSOleksandr Tymoshenko 823e53470feSOleksandr Tymoshenko /* Clear the CSR register and IRQ status register */ 824e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK); 825e53470feSOleksandr Tymoshenko for (j = 0; j < NUM_DMA_IRQS; j++) { 826e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch)); 827e53470feSOleksandr Tymoshenko } 828e53470feSOleksandr Tymoshenko 829e53470feSOleksandr Tymoshenko /* Configuration registers need to be re-written on the next xfer */ 830e53470feSOleksandr Tymoshenko sc->sc_channel[ch].need_reg_write = 1; 831e53470feSOleksandr Tymoshenko 832e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 833e53470feSOleksandr Tymoshenko 834e53470feSOleksandr Tymoshenko return (0); 835e53470feSOleksandr Tymoshenko } 836e53470feSOleksandr Tymoshenko 837e53470feSOleksandr Tymoshenko /** 838*255eff3bSPedro F. Giffuni * ti_sdma_set_xfer_endianess - sets the endianness of subsequent transfers 839*255eff3bSPedro F. Giffuni * @ch: the channel number to set the endianness of 840*255eff3bSPedro F. Giffuni * @src: the source endianness (either DMA_ENDIAN_LITTLE or DMA_ENDIAN_BIG) 841*255eff3bSPedro F. Giffuni * @dst: the destination endianness (either DMA_ENDIAN_LITTLE or DMA_ENDIAN_BIG) 842e53470feSOleksandr Tymoshenko * 843e53470feSOleksandr Tymoshenko * 844e53470feSOleksandr Tymoshenko * LOCKING: 845e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 846e53470feSOleksandr Tymoshenko * 847e53470feSOleksandr Tymoshenko * RETURNS: 848e53470feSOleksandr Tymoshenko * EH_HANDLED or EH_NOT_HANDLED 849e53470feSOleksandr Tymoshenko */ 850e53470feSOleksandr Tymoshenko int 851e53470feSOleksandr Tymoshenko ti_sdma_set_xfer_endianess(unsigned int ch, unsigned int src, unsigned int dst) 852e53470feSOleksandr Tymoshenko { 853e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 854e53470feSOleksandr Tymoshenko 855e53470feSOleksandr Tymoshenko /* Sanity check */ 856e53470feSOleksandr Tymoshenko if (sc == NULL) 857e53470feSOleksandr Tymoshenko return (ENOMEM); 858e53470feSOleksandr Tymoshenko 859e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 860e53470feSOleksandr Tymoshenko 861e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 862e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 863e53470feSOleksandr Tymoshenko return (EINVAL); 864e53470feSOleksandr Tymoshenko } 865e53470feSOleksandr Tymoshenko 866e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_SRC_ENDIANISM(1); 867e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_SRC_ENDIANISM(src); 868e53470feSOleksandr Tymoshenko 869e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DST_ENDIANISM(1); 870e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DST_ENDIANISM(dst); 871e53470feSOleksandr Tymoshenko 872e53470feSOleksandr Tymoshenko sc->sc_channel[ch].need_reg_write = 1; 873e53470feSOleksandr Tymoshenko 874e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 875e53470feSOleksandr Tymoshenko 876e53470feSOleksandr Tymoshenko return 0; 877e53470feSOleksandr Tymoshenko } 878e53470feSOleksandr Tymoshenko 879e53470feSOleksandr Tymoshenko /** 880e53470feSOleksandr Tymoshenko * ti_sdma_set_xfer_burst - sets the source and destination element size 881e53470feSOleksandr Tymoshenko * @ch: the channel number to set the burst settings of 882*255eff3bSPedro F. Giffuni * @src: the source endianness (either DMA_BURST_NONE, DMA_BURST_16, DMA_BURST_32 883e53470feSOleksandr Tymoshenko * or DMA_BURST_64) 884*255eff3bSPedro F. Giffuni * @dst: the destination endianness (either DMA_BURST_NONE, DMA_BURST_16, 885e53470feSOleksandr Tymoshenko * DMA_BURST_32 or DMA_BURST_64) 886e53470feSOleksandr Tymoshenko * 887e53470feSOleksandr Tymoshenko * This function sets the size of the elements for all subsequent transfers. 888e53470feSOleksandr Tymoshenko * 889e53470feSOleksandr Tymoshenko * LOCKING: 890e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 891e53470feSOleksandr Tymoshenko * 892e53470feSOleksandr Tymoshenko * RETURNS: 893e53470feSOleksandr Tymoshenko * EH_HANDLED or EH_NOT_HANDLED 894e53470feSOleksandr Tymoshenko */ 895e53470feSOleksandr Tymoshenko int 896e53470feSOleksandr Tymoshenko ti_sdma_set_xfer_burst(unsigned int ch, unsigned int src, unsigned int dst) 897e53470feSOleksandr Tymoshenko { 898e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 899e53470feSOleksandr Tymoshenko 900e53470feSOleksandr Tymoshenko /* Sanity check */ 901e53470feSOleksandr Tymoshenko if (sc == NULL) 902e53470feSOleksandr Tymoshenko return (ENOMEM); 903e53470feSOleksandr Tymoshenko 904e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 905e53470feSOleksandr Tymoshenko 906e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 907e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 908e53470feSOleksandr Tymoshenko return (EINVAL); 909e53470feSOleksandr Tymoshenko } 910e53470feSOleksandr Tymoshenko 911e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_SRC_BURST_MODE(0x3); 912e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_SRC_BURST_MODE(src); 913e53470feSOleksandr Tymoshenko 914e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DST_BURST_MODE(0x3); 915e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DST_BURST_MODE(dst); 916e53470feSOleksandr Tymoshenko 917e53470feSOleksandr Tymoshenko sc->sc_channel[ch].need_reg_write = 1; 918e53470feSOleksandr Tymoshenko 919e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 920e53470feSOleksandr Tymoshenko 921e53470feSOleksandr Tymoshenko return 0; 922e53470feSOleksandr Tymoshenko } 923e53470feSOleksandr Tymoshenko 924e53470feSOleksandr Tymoshenko /** 925e53470feSOleksandr Tymoshenko * ti_sdma_set_xfer_data_type - driver attach function 926*255eff3bSPedro F. Giffuni * @ch: the channel number to set the endianness of 927e53470feSOleksandr Tymoshenko * @type: the xfer data type (either DMA_DATA_8BITS_SCALAR, DMA_DATA_16BITS_SCALAR 928e53470feSOleksandr Tymoshenko * or DMA_DATA_32BITS_SCALAR) 929e53470feSOleksandr Tymoshenko * 930e53470feSOleksandr Tymoshenko * 931e53470feSOleksandr Tymoshenko * LOCKING: 932e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 933e53470feSOleksandr Tymoshenko * 934e53470feSOleksandr Tymoshenko * RETURNS: 935e53470feSOleksandr Tymoshenko * EH_HANDLED or EH_NOT_HANDLED 936e53470feSOleksandr Tymoshenko */ 937e53470feSOleksandr Tymoshenko int 938e53470feSOleksandr Tymoshenko ti_sdma_set_xfer_data_type(unsigned int ch, unsigned int type) 939e53470feSOleksandr Tymoshenko { 940e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 941e53470feSOleksandr Tymoshenko 942e53470feSOleksandr Tymoshenko /* Sanity check */ 943e53470feSOleksandr Tymoshenko if (sc == NULL) 944e53470feSOleksandr Tymoshenko return (ENOMEM); 945e53470feSOleksandr Tymoshenko 946e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 947e53470feSOleksandr Tymoshenko 948e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 949e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 950e53470feSOleksandr Tymoshenko return (EINVAL); 951e53470feSOleksandr Tymoshenko } 952e53470feSOleksandr Tymoshenko 953e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DATA_TYPE(0x3); 954e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DATA_TYPE(type); 955e53470feSOleksandr Tymoshenko 956e53470feSOleksandr Tymoshenko sc->sc_channel[ch].need_reg_write = 1; 957e53470feSOleksandr Tymoshenko 958e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 959e53470feSOleksandr Tymoshenko 960e53470feSOleksandr Tymoshenko return 0; 961e53470feSOleksandr Tymoshenko } 962e53470feSOleksandr Tymoshenko 963e53470feSOleksandr Tymoshenko /** 964e53470feSOleksandr Tymoshenko * ti_sdma_set_callback - driver attach function 965e53470feSOleksandr Tymoshenko * @dev: dma device handle 966e53470feSOleksandr Tymoshenko * 967e53470feSOleksandr Tymoshenko * 968e53470feSOleksandr Tymoshenko * 969e53470feSOleksandr Tymoshenko * LOCKING: 970e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 971e53470feSOleksandr Tymoshenko * 972e53470feSOleksandr Tymoshenko * RETURNS: 973e53470feSOleksandr Tymoshenko * EH_HANDLED or EH_NOT_HANDLED 974e53470feSOleksandr Tymoshenko */ 975e53470feSOleksandr Tymoshenko int 976e53470feSOleksandr Tymoshenko ti_sdma_set_callback(unsigned int ch, 977e53470feSOleksandr Tymoshenko void (*callback)(unsigned int ch, uint32_t status, void *data), 978e53470feSOleksandr Tymoshenko void *data) 979e53470feSOleksandr Tymoshenko { 980e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 981e53470feSOleksandr Tymoshenko 982e53470feSOleksandr Tymoshenko /* Sanity check */ 983e53470feSOleksandr Tymoshenko if (sc == NULL) 984e53470feSOleksandr Tymoshenko return (ENOMEM); 985e53470feSOleksandr Tymoshenko 986e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 987e53470feSOleksandr Tymoshenko 988e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 989e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 990e53470feSOleksandr Tymoshenko return (EINVAL); 991e53470feSOleksandr Tymoshenko } 992e53470feSOleksandr Tymoshenko 993e53470feSOleksandr Tymoshenko sc->sc_channel[ch].callback = callback; 994e53470feSOleksandr Tymoshenko sc->sc_channel[ch].callback_data = data; 995e53470feSOleksandr Tymoshenko 996e53470feSOleksandr Tymoshenko sc->sc_channel[ch].need_reg_write = 1; 997e53470feSOleksandr Tymoshenko 998e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 999e53470feSOleksandr Tymoshenko 1000e53470feSOleksandr Tymoshenko return 0; 1001e53470feSOleksandr Tymoshenko } 1002e53470feSOleksandr Tymoshenko 1003e53470feSOleksandr Tymoshenko /** 1004e53470feSOleksandr Tymoshenko * ti_sdma_sync_params - sets channel sync settings 1005e53470feSOleksandr Tymoshenko * @ch: the channel number to set the sync on 1006e53470feSOleksandr Tymoshenko * @trigger: the number of the sync trigger, this depends on what other H/W 1007e53470feSOleksandr Tymoshenko * module is triggering/receiving the DMA transactions 1008e53470feSOleksandr Tymoshenko * @mode: flags describing the sync mode to use, it may have one or more of 1009e53470feSOleksandr Tymoshenko * the following bits set; TI_SDMA_SYNC_FRAME, 1010e53470feSOleksandr Tymoshenko * TI_SDMA_SYNC_BLOCK, TI_SDMA_SYNC_TRIG_ON_SRC. 1011e53470feSOleksandr Tymoshenko * 1012e53470feSOleksandr Tymoshenko * 1013e53470feSOleksandr Tymoshenko * 1014e53470feSOleksandr Tymoshenko * LOCKING: 1015e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 1016e53470feSOleksandr Tymoshenko * 1017e53470feSOleksandr Tymoshenko * RETURNS: 1018e53470feSOleksandr Tymoshenko * EH_HANDLED or EH_NOT_HANDLED 1019e53470feSOleksandr Tymoshenko */ 1020e53470feSOleksandr Tymoshenko int 1021e53470feSOleksandr Tymoshenko ti_sdma_sync_params(unsigned int ch, unsigned int trigger, unsigned int mode) 1022e53470feSOleksandr Tymoshenko { 1023e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 1024e53470feSOleksandr Tymoshenko uint32_t ccr; 1025e53470feSOleksandr Tymoshenko 1026e53470feSOleksandr Tymoshenko /* Sanity check */ 1027e53470feSOleksandr Tymoshenko if (sc == NULL) 1028e53470feSOleksandr Tymoshenko return (ENOMEM); 1029e53470feSOleksandr Tymoshenko 1030e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 1031e53470feSOleksandr Tymoshenko 1032e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 1033e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 1034e53470feSOleksandr Tymoshenko return (EINVAL); 1035e53470feSOleksandr Tymoshenko } 1036e53470feSOleksandr Tymoshenko 1037e53470feSOleksandr Tymoshenko ccr = sc->sc_channel[ch].reg_ccr; 1038e53470feSOleksandr Tymoshenko 1039e53470feSOleksandr Tymoshenko ccr &= ~DMA4_CCR_SYNC_TRIGGER(0x7F); 1040e53470feSOleksandr Tymoshenko ccr |= DMA4_CCR_SYNC_TRIGGER(trigger + 1); 1041e53470feSOleksandr Tymoshenko 1042e53470feSOleksandr Tymoshenko if (mode & TI_SDMA_SYNC_FRAME) 1043e53470feSOleksandr Tymoshenko ccr |= DMA4_CCR_FRAME_SYNC(1); 1044e53470feSOleksandr Tymoshenko else 1045e53470feSOleksandr Tymoshenko ccr &= ~DMA4_CCR_FRAME_SYNC(1); 1046e53470feSOleksandr Tymoshenko 1047e53470feSOleksandr Tymoshenko if (mode & TI_SDMA_SYNC_BLOCK) 1048e53470feSOleksandr Tymoshenko ccr |= DMA4_CCR_BLOCK_SYNC(1); 1049e53470feSOleksandr Tymoshenko else 1050e53470feSOleksandr Tymoshenko ccr &= ~DMA4_CCR_BLOCK_SYNC(1); 1051e53470feSOleksandr Tymoshenko 1052e53470feSOleksandr Tymoshenko if (mode & TI_SDMA_SYNC_TRIG_ON_SRC) 1053e53470feSOleksandr Tymoshenko ccr |= DMA4_CCR_SEL_SRC_DST_SYNC(1); 1054e53470feSOleksandr Tymoshenko else 1055e53470feSOleksandr Tymoshenko ccr &= ~DMA4_CCR_SEL_SRC_DST_SYNC(1); 1056e53470feSOleksandr Tymoshenko 1057e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_ccr = ccr; 1058e53470feSOleksandr Tymoshenko 1059e53470feSOleksandr Tymoshenko sc->sc_channel[ch].need_reg_write = 1; 1060e53470feSOleksandr Tymoshenko 1061e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 1062e53470feSOleksandr Tymoshenko 1063e53470feSOleksandr Tymoshenko return 0; 1064e53470feSOleksandr Tymoshenko } 1065e53470feSOleksandr Tymoshenko 1066e53470feSOleksandr Tymoshenko /** 1067e53470feSOleksandr Tymoshenko * ti_sdma_set_addr_mode - driver attach function 1068*255eff3bSPedro F. Giffuni * @ch: the channel number to set the endianness of 1069e53470feSOleksandr Tymoshenko * @rd_mode: the xfer source addressing mode (either DMA_ADDR_CONSTANT, 1070e53470feSOleksandr Tymoshenko * DMA_ADDR_POST_INCREMENT, DMA_ADDR_SINGLE_INDEX or 1071e53470feSOleksandr Tymoshenko * DMA_ADDR_DOUBLE_INDEX) 1072e53470feSOleksandr Tymoshenko * @wr_mode: the xfer destination addressing mode (either DMA_ADDR_CONSTANT, 1073e53470feSOleksandr Tymoshenko * DMA_ADDR_POST_INCREMENT, DMA_ADDR_SINGLE_INDEX or 1074e53470feSOleksandr Tymoshenko * DMA_ADDR_DOUBLE_INDEX) 1075e53470feSOleksandr Tymoshenko * 1076e53470feSOleksandr Tymoshenko * 1077e53470feSOleksandr Tymoshenko * LOCKING: 1078e53470feSOleksandr Tymoshenko * DMA registers protected by internal mutex 1079e53470feSOleksandr Tymoshenko * 1080e53470feSOleksandr Tymoshenko * RETURNS: 1081e53470feSOleksandr Tymoshenko * EH_HANDLED or EH_NOT_HANDLED 1082e53470feSOleksandr Tymoshenko */ 1083e53470feSOleksandr Tymoshenko int 1084e53470feSOleksandr Tymoshenko ti_sdma_set_addr_mode(unsigned int ch, unsigned int src_mode, 1085e53470feSOleksandr Tymoshenko unsigned int dst_mode) 1086e53470feSOleksandr Tymoshenko { 1087e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = ti_sdma_sc; 1088e53470feSOleksandr Tymoshenko uint32_t ccr; 1089e53470feSOleksandr Tymoshenko 1090e53470feSOleksandr Tymoshenko /* Sanity check */ 1091e53470feSOleksandr Tymoshenko if (sc == NULL) 1092e53470feSOleksandr Tymoshenko return (ENOMEM); 1093e53470feSOleksandr Tymoshenko 1094e53470feSOleksandr Tymoshenko TI_SDMA_LOCK(sc); 1095e53470feSOleksandr Tymoshenko 1096e53470feSOleksandr Tymoshenko if ((sc->sc_active_channels & (1 << ch)) == 0) { 1097e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 1098e53470feSOleksandr Tymoshenko return (EINVAL); 1099e53470feSOleksandr Tymoshenko } 1100e53470feSOleksandr Tymoshenko 1101e53470feSOleksandr Tymoshenko ccr = sc->sc_channel[ch].reg_ccr; 1102e53470feSOleksandr Tymoshenko 1103e53470feSOleksandr Tymoshenko ccr &= ~DMA4_CCR_SRC_ADDRESS_MODE(0x3); 1104e53470feSOleksandr Tymoshenko ccr |= DMA4_CCR_SRC_ADDRESS_MODE(src_mode); 1105e53470feSOleksandr Tymoshenko 1106e53470feSOleksandr Tymoshenko ccr &= ~DMA4_CCR_DST_ADDRESS_MODE(0x3); 1107e53470feSOleksandr Tymoshenko ccr |= DMA4_CCR_DST_ADDRESS_MODE(dst_mode); 1108e53470feSOleksandr Tymoshenko 1109e53470feSOleksandr Tymoshenko sc->sc_channel[ch].reg_ccr = ccr; 1110e53470feSOleksandr Tymoshenko 1111e53470feSOleksandr Tymoshenko sc->sc_channel[ch].need_reg_write = 1; 1112e53470feSOleksandr Tymoshenko 1113e53470feSOleksandr Tymoshenko TI_SDMA_UNLOCK(sc); 1114e53470feSOleksandr Tymoshenko 1115e53470feSOleksandr Tymoshenko return 0; 1116e53470feSOleksandr Tymoshenko } 1117e53470feSOleksandr Tymoshenko 1118e53470feSOleksandr Tymoshenko /** 1119e53470feSOleksandr Tymoshenko * ti_sdma_probe - driver probe function 1120e53470feSOleksandr Tymoshenko * @dev: dma device handle 1121e53470feSOleksandr Tymoshenko * 1122e53470feSOleksandr Tymoshenko * 1123e53470feSOleksandr Tymoshenko * 1124e53470feSOleksandr Tymoshenko * RETURNS: 1125e53470feSOleksandr Tymoshenko * Always returns 0. 1126e53470feSOleksandr Tymoshenko */ 1127e53470feSOleksandr Tymoshenko static int 1128e53470feSOleksandr Tymoshenko ti_sdma_probe(device_t dev) 1129e53470feSOleksandr Tymoshenko { 1130add35ed5SIan Lepore 1131add35ed5SIan Lepore if (!ofw_bus_status_okay(dev)) 1132add35ed5SIan Lepore return (ENXIO); 1133add35ed5SIan Lepore 11345b03aba6SOleksandr Tymoshenko if (!ofw_bus_is_compatible(dev, "ti,omap4430-sdma")) 1135e53470feSOleksandr Tymoshenko return (ENXIO); 1136e53470feSOleksandr Tymoshenko 1137e53470feSOleksandr Tymoshenko device_set_desc(dev, "TI sDMA Controller"); 1138e53470feSOleksandr Tymoshenko return (0); 1139e53470feSOleksandr Tymoshenko } 1140e53470feSOleksandr Tymoshenko 1141e53470feSOleksandr Tymoshenko /** 1142e53470feSOleksandr Tymoshenko * ti_sdma_attach - driver attach function 1143e53470feSOleksandr Tymoshenko * @dev: dma device handle 1144e53470feSOleksandr Tymoshenko * 1145e53470feSOleksandr Tymoshenko * Initialises memory mapping/pointers to the DMA register set and requests 1146e53470feSOleksandr Tymoshenko * IRQs. This is effectively the setup function for the driver. 1147e53470feSOleksandr Tymoshenko * 1148e53470feSOleksandr Tymoshenko * RETURNS: 1149e53470feSOleksandr Tymoshenko * 0 on success or a negative error code failure. 1150e53470feSOleksandr Tymoshenko */ 1151e53470feSOleksandr Tymoshenko static int 1152e53470feSOleksandr Tymoshenko ti_sdma_attach(device_t dev) 1153e53470feSOleksandr Tymoshenko { 1154e53470feSOleksandr Tymoshenko struct ti_sdma_softc *sc = device_get_softc(dev); 1155e53470feSOleksandr Tymoshenko unsigned int timeout; 1156e53470feSOleksandr Tymoshenko unsigned int i; 1157e53470feSOleksandr Tymoshenko int rid; 1158e53470feSOleksandr Tymoshenko void *ihl; 1159e53470feSOleksandr Tymoshenko int err; 1160e53470feSOleksandr Tymoshenko 1161e53470feSOleksandr Tymoshenko /* Setup the basics */ 1162e53470feSOleksandr Tymoshenko sc->sc_dev = dev; 1163e53470feSOleksandr Tymoshenko 1164e53470feSOleksandr Tymoshenko /* No channels active at the moment */ 1165e53470feSOleksandr Tymoshenko sc->sc_active_channels = 0x00000000; 1166e53470feSOleksandr Tymoshenko 1167e53470feSOleksandr Tymoshenko /* Mutex to protect the shared data structures */ 1168e53470feSOleksandr Tymoshenko TI_SDMA_LOCK_INIT(sc); 1169e53470feSOleksandr Tymoshenko 1170e53470feSOleksandr Tymoshenko /* Get the memory resource for the register mapping */ 1171e53470feSOleksandr Tymoshenko rid = 0; 1172e53470feSOleksandr Tymoshenko sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 1173e53470feSOleksandr Tymoshenko if (sc->sc_mem_res == NULL) 1174e53470feSOleksandr Tymoshenko panic("%s: Cannot map registers", device_get_name(dev)); 1175e53470feSOleksandr Tymoshenko 1176e53470feSOleksandr Tymoshenko /* Enable the interface and functional clocks */ 1177e53470feSOleksandr Tymoshenko ti_prcm_clk_enable(SDMA_CLK); 1178e53470feSOleksandr Tymoshenko 1179e53470feSOleksandr Tymoshenko /* Read the sDMA revision register and sanity check it's known */ 1180e53470feSOleksandr Tymoshenko sc->sc_hw_rev = ti_sdma_read_4(sc, DMA4_REVISION); 1181e53470feSOleksandr Tymoshenko device_printf(dev, "sDMA revision %08x\n", sc->sc_hw_rev); 1182e53470feSOleksandr Tymoshenko 1183e53470feSOleksandr Tymoshenko if (!ti_sdma_is_omap4_rev(sc) && !ti_sdma_is_omap3_rev(sc)) { 1184e53470feSOleksandr Tymoshenko device_printf(sc->sc_dev, "error - unknown sDMA H/W revision\n"); 1185e53470feSOleksandr Tymoshenko return (EINVAL); 1186e53470feSOleksandr Tymoshenko } 1187e53470feSOleksandr Tymoshenko 1188e53470feSOleksandr Tymoshenko /* Disable all interrupts */ 1189e53470feSOleksandr Tymoshenko for (i = 0; i < NUM_DMA_IRQS; i++) { 1190e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_IRQENABLE_L(i), 0x00000000); 1191e53470feSOleksandr Tymoshenko } 1192e53470feSOleksandr Tymoshenko 1193e53470feSOleksandr Tymoshenko /* Soft-reset is only supported on pre-OMAP44xx devices */ 1194e53470feSOleksandr Tymoshenko if (ti_sdma_is_omap3_rev(sc)) { 1195e53470feSOleksandr Tymoshenko 1196e53470feSOleksandr Tymoshenko /* Soft-reset */ 1197e53470feSOleksandr Tymoshenko ti_sdma_write_4(sc, DMA4_OCP_SYSCONFIG, 0x0002); 1198e53470feSOleksandr Tymoshenko 1199e53470feSOleksandr Tymoshenko /* Set the timeout to 100ms*/ 1200e53470feSOleksandr Tymoshenko timeout = (hz < 10) ? 1 : ((100 * hz) / 1000); 1201e53470feSOleksandr Tymoshenko 1202e53470feSOleksandr Tymoshenko /* Wait for DMA reset to complete */ 1203e53470feSOleksandr Tymoshenko while ((ti_sdma_read_4(sc, DMA4_SYSSTATUS) & 0x1) == 0x0) { 1204e53470feSOleksandr Tymoshenko 1205e53470feSOleksandr Tymoshenko /* Sleep for a tick */ 1206e53470feSOleksandr Tymoshenko pause("DMARESET", 1); 1207e53470feSOleksandr Tymoshenko 1208e53470feSOleksandr Tymoshenko if (timeout-- == 0) { 1209e53470feSOleksandr Tymoshenko device_printf(sc->sc_dev, "sDMA reset operation timed out\n"); 1210e53470feSOleksandr Tymoshenko return (EINVAL); 1211e53470feSOleksandr Tymoshenko } 1212e53470feSOleksandr Tymoshenko } 1213e53470feSOleksandr Tymoshenko } 1214e53470feSOleksandr Tymoshenko 1215e53470feSOleksandr Tymoshenko /* 1216e53470feSOleksandr Tymoshenko * Install interrupt handlers for the for possible interrupts. Any channel 1217e53470feSOleksandr Tymoshenko * can trip one of the four IRQs 1218e53470feSOleksandr Tymoshenko */ 1219e53470feSOleksandr Tymoshenko rid = 0; 1220e53470feSOleksandr Tymoshenko sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 1221e53470feSOleksandr Tymoshenko RF_ACTIVE | RF_SHAREABLE); 1222e53470feSOleksandr Tymoshenko if (sc->sc_irq_res == NULL) 1223e53470feSOleksandr Tymoshenko panic("Unable to setup the dma irq handler.\n"); 1224e53470feSOleksandr Tymoshenko 1225e53470feSOleksandr Tymoshenko err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 1226e53470feSOleksandr Tymoshenko NULL, ti_sdma_intr, NULL, &ihl); 1227e53470feSOleksandr Tymoshenko if (err) 1228e53470feSOleksandr Tymoshenko panic("%s: Cannot register IRQ", device_get_name(dev)); 1229e53470feSOleksandr Tymoshenko 1230e53470feSOleksandr Tymoshenko /* Store the DMA structure globally ... this driver should never be unloaded */ 1231e53470feSOleksandr Tymoshenko ti_sdma_sc = sc; 1232e53470feSOleksandr Tymoshenko 1233e53470feSOleksandr Tymoshenko return (0); 1234e53470feSOleksandr Tymoshenko } 1235e53470feSOleksandr Tymoshenko 1236e53470feSOleksandr Tymoshenko static device_method_t ti_sdma_methods[] = { 1237e53470feSOleksandr Tymoshenko DEVMETHOD(device_probe, ti_sdma_probe), 1238e53470feSOleksandr Tymoshenko DEVMETHOD(device_attach, ti_sdma_attach), 1239e53470feSOleksandr Tymoshenko {0, 0}, 1240e53470feSOleksandr Tymoshenko }; 1241e53470feSOleksandr Tymoshenko 1242e53470feSOleksandr Tymoshenko static driver_t ti_sdma_driver = { 1243e53470feSOleksandr Tymoshenko "ti_sdma", 1244e53470feSOleksandr Tymoshenko ti_sdma_methods, 1245e53470feSOleksandr Tymoshenko sizeof(struct ti_sdma_softc), 1246e53470feSOleksandr Tymoshenko }; 1247e53470feSOleksandr Tymoshenko static devclass_t ti_sdma_devclass; 1248e53470feSOleksandr Tymoshenko 1249e53470feSOleksandr Tymoshenko DRIVER_MODULE(ti_sdma, simplebus, ti_sdma_driver, ti_sdma_devclass, 0, 0); 1250e53470feSOleksandr Tymoshenko MODULE_DEPEND(ti_sdma, ti_prcm, 1, 1, 1); 1251