1 /* 2 * Bestcomm ATA task driver 3 * 4 * 5 * Patterned after bestcomm/fec.c by Dale Farnsworth <dfarnsworth@mvista.com> 6 * 2003-2004 (c) MontaVista, Software, Inc. 7 * 8 * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com> 9 * Copyright (C) 2006 Freescale - John Rigby 10 * 11 * This file is licensed under the terms of the GNU General Public License 12 * version 2. This program is licensed "as is" without any warranty of any 13 * kind, whether express or implied. 14 */ 15 16 #include <linux/kernel.h> 17 #include <linux/module.h> 18 #include <linux/types.h> 19 #include <asm/io.h> 20 21 #include <linux/fsl/bestcomm/bestcomm.h> 22 #include <linux/fsl/bestcomm/bestcomm_priv.h> 23 #include <linux/fsl/bestcomm/ata.h> 24 25 26 /* ======================================================================== */ 27 /* Task image/var/inc */ 28 /* ======================================================================== */ 29 30 /* ata task image */ 31 extern u32 bcom_ata_task[]; 32 33 /* ata task vars that need to be set before enabling the task */ 34 struct bcom_ata_var { 35 u32 enable; /* (u16*) address of task's control register */ 36 u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */ 37 u32 bd_last; /* (struct bcom_bd*) end of ring buffer */ 38 u32 bd_start; /* (struct bcom_bd*) current bd */ 39 u32 buffer_size; /* size of receive buffer */ 40 }; 41 42 /* ata task incs that need to be set before enabling the task */ 43 struct bcom_ata_inc { 44 u16 pad0; 45 s16 incr_bytes; 46 u16 pad1; 47 s16 incr_dst; 48 u16 pad2; 49 s16 incr_src; 50 }; 51 52 53 /* ======================================================================== */ 54 /* Task support code */ 55 /* ======================================================================== */ 56 57 struct bcom_task * 58 bcom_ata_init(int queue_len, int maxbufsize) 59 { 60 struct bcom_task *tsk; 61 struct bcom_ata_var *var; 62 struct bcom_ata_inc *inc; 63 64 /* Prefetch breaks ATA DMA. Turn it off for ATA DMA */ 65 bcom_disable_prefetch(); 66 67 tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_ata_bd), 0); 68 if (!tsk) 69 return NULL; 70 71 tsk->flags = BCOM_FLAGS_NONE; 72 73 bcom_ata_reset_bd(tsk); 74 75 var = (struct bcom_ata_var *) bcom_task_var(tsk->tasknum); 76 inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum); 77 78 if (bcom_load_image(tsk->tasknum, bcom_ata_task)) { 79 bcom_task_free(tsk); 80 return NULL; 81 } 82 83 var->enable = bcom_eng->regs_base + 84 offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]); 85 var->bd_base = tsk->bd_pa; 86 var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size); 87 var->bd_start = tsk->bd_pa; 88 var->buffer_size = maxbufsize; 89 90 /* Configure some stuff */ 91 bcom_set_task_pragma(tsk->tasknum, BCOM_ATA_PRAGMA); 92 bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum); 93 94 out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ATA_RX], BCOM_IPR_ATA_RX); 95 out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ATA_TX], BCOM_IPR_ATA_TX); 96 97 out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */ 98 99 return tsk; 100 } 101 EXPORT_SYMBOL_GPL(bcom_ata_init); 102 103 void bcom_ata_rx_prepare(struct bcom_task *tsk) 104 { 105 struct bcom_ata_inc *inc; 106 107 inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum); 108 109 inc->incr_bytes = -(s16)sizeof(u32); 110 inc->incr_src = 0; 111 inc->incr_dst = sizeof(u32); 112 113 bcom_set_initiator(tsk->tasknum, BCOM_INITIATOR_ATA_RX); 114 } 115 EXPORT_SYMBOL_GPL(bcom_ata_rx_prepare); 116 117 void bcom_ata_tx_prepare(struct bcom_task *tsk) 118 { 119 struct bcom_ata_inc *inc; 120 121 inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum); 122 123 inc->incr_bytes = -(s16)sizeof(u32); 124 inc->incr_src = sizeof(u32); 125 inc->incr_dst = 0; 126 127 bcom_set_initiator(tsk->tasknum, BCOM_INITIATOR_ATA_TX); 128 } 129 EXPORT_SYMBOL_GPL(bcom_ata_tx_prepare); 130 131 void bcom_ata_reset_bd(struct bcom_task *tsk) 132 { 133 struct bcom_ata_var *var; 134 135 /* Reset all BD */ 136 memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); 137 138 tsk->index = 0; 139 tsk->outdex = 0; 140 141 var = (struct bcom_ata_var *) bcom_task_var(tsk->tasknum); 142 var->bd_start = var->bd_base; 143 } 144 EXPORT_SYMBOL_GPL(bcom_ata_reset_bd); 145 146 void bcom_ata_release(struct bcom_task *tsk) 147 { 148 /* Nothing special for the ATA tasks */ 149 bcom_task_free(tsk); 150 } 151 EXPORT_SYMBOL_GPL(bcom_ata_release); 152 153 154 MODULE_DESCRIPTION("BestComm ATA task driver"); 155 MODULE_AUTHOR("John Rigby"); 156 MODULE_LICENSE("GPL v2"); 157 158