Path: blob/master/arch/arm/mach-iop13xx/include/mach/adma.h
17778 views
/*1* Copyright(c) 2006, Intel Corporation.2*3* This program is free software; you can redistribute it and/or modify it4* under the terms and conditions of the GNU General Public License,5* version 2, as published by the Free Software Foundation.6*7* This program is distributed in the hope it will be useful, but WITHOUT8* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or9* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for10* more details.11*12* You should have received a copy of the GNU General Public License along with13* this program; if not, write to the Free Software Foundation, Inc.,14* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.15*16*/17#ifndef _ADMA_H18#define _ADMA_H19#include <linux/types.h>20#include <linux/io.h>21#include <mach/hardware.h>22#include <asm/hardware/iop_adma.h>2324#define ADMA_ACCR(chan) (chan->mmr_base + 0x0)25#define ADMA_ACSR(chan) (chan->mmr_base + 0x4)26#define ADMA_ADAR(chan) (chan->mmr_base + 0x8)27#define ADMA_IIPCR(chan) (chan->mmr_base + 0x18)28#define ADMA_IIPAR(chan) (chan->mmr_base + 0x1c)29#define ADMA_IIPUAR(chan) (chan->mmr_base + 0x20)30#define ADMA_ANDAR(chan) (chan->mmr_base + 0x24)31#define ADMA_ADCR(chan) (chan->mmr_base + 0x28)32#define ADMA_CARMD(chan) (chan->mmr_base + 0x2c)33#define ADMA_ABCR(chan) (chan->mmr_base + 0x30)34#define ADMA_DLADR(chan) (chan->mmr_base + 0x34)35#define ADMA_DUADR(chan) (chan->mmr_base + 0x38)36#define ADMA_SLAR(src, chan) (chan->mmr_base + (0x3c + (src << 3)))37#define ADMA_SUAR(src, chan) (chan->mmr_base + (0x40 + (src << 3)))3839struct iop13xx_adma_src {40u32 src_addr;41union {42u32 upper_src_addr;43struct {44unsigned int pq_upper_src_addr:24;45unsigned int pq_dmlt:8;46};47};48};4950struct iop13xx_adma_desc_ctrl {51unsigned int int_en:1;52unsigned int xfer_dir:2;53unsigned int src_select:4;54unsigned int zero_result:1;55unsigned int block_fill_en:1;56unsigned int crc_gen_en:1;57unsigned int crc_xfer_dis:1;58unsigned int crc_seed_fetch_dis:1;59unsigned int status_write_back_en:1;60unsigned int endian_swap_en:1;61unsigned int reserved0:2;62unsigned int pq_update_xfer_en:1;63unsigned int dual_xor_en:1;64unsigned int pq_xfer_en:1;65unsigned int p_xfer_dis:1;66unsigned int reserved1:10;67unsigned int relax_order_en:1;68unsigned int no_snoop_en:1;69};7071struct iop13xx_adma_byte_count {72unsigned int byte_count:24;73unsigned int host_if:3;74unsigned int reserved:2;75unsigned int zero_result_err_q:1;76unsigned int zero_result_err:1;77unsigned int tx_complete:1;78};7980struct iop13xx_adma_desc_hw {81u32 next_desc;82union {83u32 desc_ctrl;84struct iop13xx_adma_desc_ctrl desc_ctrl_field;85};86union {87u32 crc_addr;88u32 block_fill_data;89u32 q_dest_addr;90};91union {92u32 byte_count;93struct iop13xx_adma_byte_count byte_count_field;94};95union {96u32 dest_addr;97u32 p_dest_addr;98};99union {100u32 upper_dest_addr;101u32 pq_upper_dest_addr;102};103struct iop13xx_adma_src src[1];104};105106struct iop13xx_adma_desc_dual_xor {107u32 next_desc;108u32 desc_ctrl;109u32 reserved;110u32 byte_count;111u32 h_dest_addr;112u32 h_upper_dest_addr;113u32 src0_addr;114u32 upper_src0_addr;115u32 src1_addr;116u32 upper_src1_addr;117u32 h_src_addr;118u32 h_upper_src_addr;119u32 d_src_addr;120u32 d_upper_src_addr;121u32 d_dest_addr;122u32 d_upper_dest_addr;123};124125struct iop13xx_adma_desc_pq_update {126u32 next_desc;127u32 desc_ctrl;128u32 reserved;129u32 byte_count;130u32 p_dest_addr;131u32 p_upper_dest_addr;132u32 src0_addr;133u32 upper_src0_addr;134u32 src1_addr;135u32 upper_src1_addr;136u32 p_src_addr;137u32 p_upper_src_addr;138u32 q_src_addr;139struct {140unsigned int q_upper_src_addr:24;141unsigned int q_dmlt:8;142};143u32 q_dest_addr;144u32 q_upper_dest_addr;145};146147static inline int iop_adma_get_max_xor(void)148{149return 16;150}151152#define iop_adma_get_max_pq iop_adma_get_max_xor153154static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)155{156return __raw_readl(ADMA_ADAR(chan));157}158159static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,160u32 next_desc_addr)161{162__raw_writel(next_desc_addr, ADMA_ANDAR(chan));163}164165#define ADMA_STATUS_BUSY (1 << 13)166167static inline char iop_chan_is_busy(struct iop_adma_chan *chan)168{169if (__raw_readl(ADMA_ACSR(chan)) &170ADMA_STATUS_BUSY)171return 1;172else173return 0;174}175176static inline int177iop_chan_get_desc_align(struct iop_adma_chan *chan, int num_slots)178{179return 1;180}181#define iop_desc_is_aligned(x, y) 1182183static inline int184iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)185{186*slots_per_op = 1;187return 1;188}189190#define iop_chan_interrupt_slot_count(s, c) iop_chan_memcpy_slot_count(0, s)191192static inline int193iop_chan_memset_slot_count(size_t len, int *slots_per_op)194{195*slots_per_op = 1;196return 1;197}198199static inline int200iop_chan_xor_slot_count(size_t len, int src_cnt, int *slots_per_op)201{202static const char slot_count_table[] = { 1, 2, 2, 2,2032, 3, 3, 3,2043, 4, 4, 4,2054, 5, 5, 5,206};207*slots_per_op = slot_count_table[src_cnt - 1];208return *slots_per_op;209}210211#define ADMA_MAX_BYTE_COUNT (16 * 1024 * 1024)212#define IOP_ADMA_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT213#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT214#define IOP_ADMA_XOR_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT215#define IOP_ADMA_PQ_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT216#define iop_chan_zero_sum_slot_count(l, s, o) iop_chan_xor_slot_count(l, s, o)217#define iop_chan_pq_slot_count iop_chan_xor_slot_count218#define iop_chan_pq_zero_sum_slot_count iop_chan_xor_slot_count219220static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc,221struct iop_adma_chan *chan)222{223struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;224return hw_desc->dest_addr;225}226227static inline u32 iop_desc_get_qdest_addr(struct iop_adma_desc_slot *desc,228struct iop_adma_chan *chan)229{230struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;231return hw_desc->q_dest_addr;232}233234static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,235struct iop_adma_chan *chan)236{237struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;238return hw_desc->byte_count_field.byte_count;239}240241static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,242struct iop_adma_chan *chan,243int src_idx)244{245struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;246return hw_desc->src[src_idx].src_addr;247}248249static inline u32 iop_desc_get_src_count(struct iop_adma_desc_slot *desc,250struct iop_adma_chan *chan)251{252struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;253return hw_desc->desc_ctrl_field.src_select + 1;254}255256static inline void257iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, unsigned long flags)258{259struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;260union {261u32 value;262struct iop13xx_adma_desc_ctrl field;263} u_desc_ctrl;264265u_desc_ctrl.value = 0;266u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */267u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;268hw_desc->desc_ctrl = u_desc_ctrl.value;269hw_desc->crc_addr = 0;270}271272static inline void273iop_desc_init_memset(struct iop_adma_desc_slot *desc, unsigned long flags)274{275struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;276union {277u32 value;278struct iop13xx_adma_desc_ctrl field;279} u_desc_ctrl;280281u_desc_ctrl.value = 0;282u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */283u_desc_ctrl.field.block_fill_en = 1;284u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;285hw_desc->desc_ctrl = u_desc_ctrl.value;286hw_desc->crc_addr = 0;287}288289/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */290static inline void291iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt,292unsigned long flags)293{294struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;295union {296u32 value;297struct iop13xx_adma_desc_ctrl field;298} u_desc_ctrl;299300u_desc_ctrl.value = 0;301u_desc_ctrl.field.src_select = src_cnt - 1;302u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */303u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;304hw_desc->desc_ctrl = u_desc_ctrl.value;305hw_desc->crc_addr = 0;306307}308#define iop_desc_init_null_xor(d, s, i) iop_desc_init_xor(d, s, i)309310/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */311static inline int312iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt,313unsigned long flags)314{315struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;316union {317u32 value;318struct iop13xx_adma_desc_ctrl field;319} u_desc_ctrl;320321u_desc_ctrl.value = 0;322u_desc_ctrl.field.src_select = src_cnt - 1;323u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */324u_desc_ctrl.field.zero_result = 1;325u_desc_ctrl.field.status_write_back_en = 1;326u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;327hw_desc->desc_ctrl = u_desc_ctrl.value;328hw_desc->crc_addr = 0;329330return 1;331}332333static inline void334iop_desc_init_pq(struct iop_adma_desc_slot *desc, int src_cnt,335unsigned long flags)336{337struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;338union {339u32 value;340struct iop13xx_adma_desc_ctrl field;341} u_desc_ctrl;342343u_desc_ctrl.value = 0;344u_desc_ctrl.field.src_select = src_cnt - 1;345u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */346u_desc_ctrl.field.pq_xfer_en = 1;347u_desc_ctrl.field.p_xfer_dis = !!(flags & DMA_PREP_PQ_DISABLE_P);348u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;349hw_desc->desc_ctrl = u_desc_ctrl.value;350}351352static inline int iop_desc_is_pq(struct iop_adma_desc_slot *desc)353{354struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;355union {356u32 value;357struct iop13xx_adma_desc_ctrl field;358} u_desc_ctrl;359360u_desc_ctrl.value = hw_desc->desc_ctrl;361return u_desc_ctrl.field.pq_xfer_en;362}363364static inline void365iop_desc_init_pq_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt,366unsigned long flags)367{368struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;369union {370u32 value;371struct iop13xx_adma_desc_ctrl field;372} u_desc_ctrl;373374u_desc_ctrl.value = 0;375u_desc_ctrl.field.src_select = src_cnt - 1;376u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */377u_desc_ctrl.field.zero_result = 1;378u_desc_ctrl.field.status_write_back_en = 1;379u_desc_ctrl.field.pq_xfer_en = 1;380u_desc_ctrl.field.p_xfer_dis = !!(flags & DMA_PREP_PQ_DISABLE_P);381u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;382hw_desc->desc_ctrl = u_desc_ctrl.value;383}384385static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,386struct iop_adma_chan *chan,387u32 byte_count)388{389struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;390hw_desc->byte_count = byte_count;391}392393static inline void394iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)395{396int slots_per_op = desc->slots_per_op;397struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;398int i = 0;399400if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {401hw_desc->byte_count = len;402} else {403do {404iter = iop_hw_desc_slot_idx(hw_desc, i);405iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;406len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;407i += slots_per_op;408} while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);409410if (len) {411iter = iop_hw_desc_slot_idx(hw_desc, i);412iter->byte_count = len;413}414}415}416417#define iop_desc_set_pq_zero_sum_byte_count iop_desc_set_zero_sum_byte_count418419static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,420struct iop_adma_chan *chan,421dma_addr_t addr)422{423struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;424hw_desc->dest_addr = addr;425hw_desc->upper_dest_addr = 0;426}427428static inline void429iop_desc_set_pq_addr(struct iop_adma_desc_slot *desc, dma_addr_t *addr)430{431struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;432433hw_desc->dest_addr = addr[0];434hw_desc->q_dest_addr = addr[1];435hw_desc->upper_dest_addr = 0;436}437438static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,439dma_addr_t addr)440{441struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;442hw_desc->src[0].src_addr = addr;443hw_desc->src[0].upper_src_addr = 0;444}445446static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,447int src_idx, dma_addr_t addr)448{449int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;450struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;451int i = 0;452453do {454iter = iop_hw_desc_slot_idx(hw_desc, i);455iter->src[src_idx].src_addr = addr;456iter->src[src_idx].upper_src_addr = 0;457slot_cnt -= slots_per_op;458if (slot_cnt) {459i += slots_per_op;460addr += IOP_ADMA_XOR_MAX_BYTE_COUNT;461}462} while (slot_cnt);463}464465static inline void466iop_desc_set_pq_src_addr(struct iop_adma_desc_slot *desc, int src_idx,467dma_addr_t addr, unsigned char coef)468{469int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;470struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;471struct iop13xx_adma_src *src;472int i = 0;473474do {475iter = iop_hw_desc_slot_idx(hw_desc, i);476src = &iter->src[src_idx];477src->src_addr = addr;478src->pq_upper_src_addr = 0;479src->pq_dmlt = coef;480slot_cnt -= slots_per_op;481if (slot_cnt) {482i += slots_per_op;483addr += IOP_ADMA_PQ_MAX_BYTE_COUNT;484}485} while (slot_cnt);486}487488static inline void489iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,490struct iop_adma_chan *chan)491{492iop_desc_init_memcpy(desc, 1);493iop_desc_set_byte_count(desc, chan, 0);494iop_desc_set_dest_addr(desc, chan, 0);495iop_desc_set_memcpy_src_addr(desc, 0);496}497498#define iop_desc_set_zero_sum_src_addr iop_desc_set_xor_src_addr499#define iop_desc_set_pq_zero_sum_src_addr iop_desc_set_pq_src_addr500501static inline void502iop_desc_set_pq_zero_sum_addr(struct iop_adma_desc_slot *desc, int pq_idx,503dma_addr_t *src)504{505iop_desc_set_xor_src_addr(desc, pq_idx, src[pq_idx]);506iop_desc_set_xor_src_addr(desc, pq_idx+1, src[pq_idx+1]);507}508509static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,510u32 next_desc_addr)511{512struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;513514iop_paranoia(hw_desc->next_desc);515hw_desc->next_desc = next_desc_addr;516}517518static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)519{520struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;521return hw_desc->next_desc;522}523524static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)525{526struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;527hw_desc->next_desc = 0;528}529530static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,531u32 val)532{533struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;534hw_desc->block_fill_data = val;535}536537static inline enum sum_check_flags538iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)539{540struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;541struct iop13xx_adma_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;542struct iop13xx_adma_byte_count byte_count = hw_desc->byte_count_field;543enum sum_check_flags flags;544545BUG_ON(!(byte_count.tx_complete && desc_ctrl.zero_result));546547flags = byte_count.zero_result_err_q << SUM_CHECK_Q;548flags |= byte_count.zero_result_err << SUM_CHECK_P;549550return flags;551}552553static inline void iop_chan_append(struct iop_adma_chan *chan)554{555u32 adma_accr;556557adma_accr = __raw_readl(ADMA_ACCR(chan));558adma_accr |= 0x2;559__raw_writel(adma_accr, ADMA_ACCR(chan));560}561562static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)563{564return __raw_readl(ADMA_ACSR(chan));565}566567static inline void iop_chan_disable(struct iop_adma_chan *chan)568{569u32 adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));570adma_chan_ctrl &= ~0x1;571__raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));572}573574static inline void iop_chan_enable(struct iop_adma_chan *chan)575{576u32 adma_chan_ctrl;577578adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));579adma_chan_ctrl |= 0x1;580__raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));581}582583static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)584{585u32 status = __raw_readl(ADMA_ACSR(chan));586status &= (1 << 12);587__raw_writel(status, ADMA_ACSR(chan));588}589590static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)591{592u32 status = __raw_readl(ADMA_ACSR(chan));593status &= (1 << 11);594__raw_writel(status, ADMA_ACSR(chan));595}596597static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)598{599u32 status = __raw_readl(ADMA_ACSR(chan));600status &= (1 << 9) | (1 << 5) | (1 << 4) | (1 << 3);601__raw_writel(status, ADMA_ACSR(chan));602}603604static inline int605iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)606{607return test_bit(9, &status);608}609610static inline int611iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)612{613return test_bit(5, &status);614}615616static inline int617iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)618{619return test_bit(4, &status);620}621622static inline int623iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)624{625return test_bit(3, &status);626}627628static inline int629iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)630{631return 0;632}633634static inline int635iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)636{637return 0;638}639640static inline int641iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)642{643return 0;644}645646#endif /* _ADMA_H */647648649