| Sylvain Munaut | 9ea68df | 2007-09-16 20:53:28 +1000 | [diff] [blame] | 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 "bestcomm.h" | 
|  | 22 | #include "bestcomm_priv.h" | 
|  | 23 | #include "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 |  | 
| Grant Likely | aaab5e8 | 2008-12-21 02:54:28 -0700 | [diff] [blame] | 64 | /* Prefetch breaks ATA DMA.  Turn it off for ATA DMA */ | 
|  | 65 | bcom_disable_prefetch(); | 
|  | 66 |  | 
| Sylvain Munaut | 9ea68df | 2007-09-16 20:53:28 +1000 | [diff] [blame] | 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 |  |