diff options
| -rw-r--r-- | arch/powerpc/sysdev/bestcomm/ata.h | 17 | ||||
| -rw-r--r-- | drivers/ata/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/ata/pata_mpc52xx.c | 546 |
3 files changed, 488 insertions, 78 deletions
diff --git a/arch/powerpc/sysdev/bestcomm/ata.h b/arch/powerpc/sysdev/bestcomm/ata.h index 0374322be93f..0b2371811334 100644 --- a/arch/powerpc/sysdev/bestcomm/ata.h +++ b/arch/powerpc/sysdev/bestcomm/ata.h | |||
| @@ -20,18 +20,11 @@ struct bcom_ata_bd { | |||
| 20 | u32 dst_pa; | 20 | u32 dst_pa; |
| 21 | }; | 21 | }; |
| 22 | 22 | ||
| 23 | extern struct bcom_task * | 23 | extern struct bcom_task * bcom_ata_init(int queue_len, int maxbufsize); |
| 24 | bcom_ata_init(int queue_len, int maxbufsize); | 24 | extern void bcom_ata_rx_prepare(struct bcom_task *tsk); |
| 25 | 25 | extern void bcom_ata_tx_prepare(struct bcom_task *tsk); | |
| 26 | extern void | 26 | extern void bcom_ata_reset_bd(struct bcom_task *tsk); |
| 27 | bcom_ata_rx_prepare(struct bcom_task *tsk); | 27 | extern void bcom_ata_release(struct bcom_task *tsk); |
| 28 | |||
| 29 | extern void | ||
| 30 | bcom_ata_tx_prepare(struct bcom_task *tsk); | ||
| 31 | |||
| 32 | extern void | ||
| 33 | bcom_ata_reset_bd(struct bcom_task *tsk); | ||
| 34 | |||
| 35 | 28 | ||
| 36 | #endif /* __BESTCOMM_ATA_H__ */ | 29 | #endif /* __BESTCOMM_ATA_H__ */ |
| 37 | 30 | ||
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 421b7c71e72d..1a7be96d627b 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
| @@ -456,7 +456,8 @@ config PATA_MARVELL | |||
| 456 | 456 | ||
| 457 | config PATA_MPC52xx | 457 | config PATA_MPC52xx |
| 458 | tristate "Freescale MPC52xx SoC internal IDE" | 458 | tristate "Freescale MPC52xx SoC internal IDE" |
| 459 | depends on PPC_MPC52xx | 459 | depends on PPC_MPC52xx && PPC_BESTCOMM |
| 460 | select PPC_BESTCOMM_ATA | ||
| 460 | help | 461 | help |
| 461 | This option enables support for integrated IDE controller | 462 | This option enables support for integrated IDE controller |
| 462 | of the Freescale MPC52xx SoC. | 463 | of the Freescale MPC52xx SoC. |
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index a9e827356d06..50ae6d13078a 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c | |||
| @@ -6,6 +6,9 @@ | |||
| 6 | * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com> | 6 | * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com> |
| 7 | * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt | 7 | * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt |
| 8 | * | 8 | * |
| 9 | * UDMA support based on patches by Freescale (Bernard Kuhn, John Rigby), | ||
| 10 | * Domen Puncer and Tim Yamin. | ||
| 11 | * | ||
| 9 | * This file is licensed under the terms of the GNU General Public License | 12 | * This file is licensed under the terms of the GNU General Public License |
| 10 | * version 2. This program is licensed "as is" without any warranty of any | 13 | * version 2. This program is licensed "as is" without any warranty of any |
| 11 | * kind, whether express or implied. | 14 | * kind, whether express or implied. |
| @@ -17,28 +20,46 @@ | |||
| 17 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
| 18 | #include <linux/libata.h> | 21 | #include <linux/libata.h> |
| 19 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
| 23 | #include <linux/types.h> | ||
| 20 | 24 | ||
| 21 | #include <asm/types.h> | 25 | #include <asm/cacheflush.h> |
| 22 | #include <asm/prom.h> | 26 | #include <asm/prom.h> |
| 23 | #include <asm/mpc52xx.h> | 27 | #include <asm/mpc52xx.h> |
| 24 | 28 | ||
| 29 | #include <sysdev/bestcomm/bestcomm.h> | ||
| 30 | #include <sysdev/bestcomm/bestcomm_priv.h> | ||
| 31 | #include <sysdev/bestcomm/ata.h> | ||
| 25 | 32 | ||
| 26 | #define DRV_NAME "mpc52xx_ata" | 33 | #define DRV_NAME "mpc52xx_ata" |
| 27 | #define DRV_VERSION "0.1.2" | ||
| 28 | |||
| 29 | 34 | ||
| 30 | /* Private structures used by the driver */ | 35 | /* Private structures used by the driver */ |
| 31 | struct mpc52xx_ata_timings { | 36 | struct mpc52xx_ata_timings { |
| 32 | u32 pio1; | 37 | u32 pio1; |
| 33 | u32 pio2; | 38 | u32 pio2; |
| 39 | u32 mdma1; | ||
| 40 | u32 mdma2; | ||
| 41 | u32 udma1; | ||
| 42 | u32 udma2; | ||
| 43 | u32 udma3; | ||
| 44 | u32 udma4; | ||
| 45 | u32 udma5; | ||
| 46 | int using_udma; | ||
| 34 | }; | 47 | }; |
| 35 | 48 | ||
| 36 | struct mpc52xx_ata_priv { | 49 | struct mpc52xx_ata_priv { |
| 37 | unsigned int ipb_period; | 50 | unsigned int ipb_period; |
| 38 | struct mpc52xx_ata __iomem * ata_regs; | 51 | struct mpc52xx_ata __iomem *ata_regs; |
| 52 | phys_addr_t ata_regs_pa; | ||
| 39 | int ata_irq; | 53 | int ata_irq; |
| 40 | struct mpc52xx_ata_timings timings[2]; | 54 | struct mpc52xx_ata_timings timings[2]; |
| 41 | int csel; | 55 | int csel; |
| 56 | |||
| 57 | /* DMA */ | ||
| 58 | struct bcom_task *dmatsk; | ||
| 59 | const struct udmaspec *udmaspec; | ||
| 60 | const struct mdmaspec *mdmaspec; | ||
| 61 | int mpc52xx_ata_dma_last_write; | ||
| 62 | int waiting_for_dma; | ||
| 42 | }; | 63 | }; |
| 43 | 64 | ||
| 44 | 65 | ||
| @@ -53,6 +74,107 @@ static const int ataspec_ta[5] = { 35, 35, 35, 35, 35}; | |||
| 53 | 74 | ||
| 54 | #define CALC_CLKCYC(c,v) ((((v)+(c)-1)/(c))) | 75 | #define CALC_CLKCYC(c,v) ((((v)+(c)-1)/(c))) |
| 55 | 76 | ||
| 77 | /* ======================================================================== */ | ||
| 78 | |||
| 79 | /* ATAPI-4 MDMA specs (in clocks) */ | ||
| 80 | struct mdmaspec { | ||
| 81 | u32 t0M; | ||
| 82 | u32 td; | ||
| 83 | u32 th; | ||
| 84 | u32 tj; | ||
| 85 | u32 tkw; | ||
| 86 | u32 tm; | ||
| 87 | u32 tn; | ||
| 88 | }; | ||
| 89 | |||
| 90 | static const struct mdmaspec mdmaspec66[3] = { | ||
| 91 | { .t0M = 32, .td = 15, .th = 2, .tj = 2, .tkw = 15, .tm = 4, .tn = 1 }, | ||
| 92 | { .t0M = 10, .td = 6, .th = 1, .tj = 1, .tkw = 4, .tm = 2, .tn = 1 }, | ||
| 93 | { .t0M = 8, .td = 5, .th = 1, .tj = 1, .tkw = 2, .tm = 2, .tn = 1 }, | ||
| 94 | }; | ||
| 95 | |||
| 96 | static const struct mdmaspec mdmaspec132[3] = { | ||
| 97 | { .t0M = 64, .td = 29, .th = 3, .tj = 3, .tkw = 29, .tm = 7, .tn = 2 }, | ||
| 98 | { .t0M = 20, .td = 11, .th = 2, .tj = 1, .tkw = 7, .tm = 4, .tn = 1 }, | ||
| 99 | { .t0M = 16, .td = 10, .th = 2, .tj = 1, .tkw = 4, .tm = 4, .tn = 1 }, | ||
| 100 | }; | ||
| 101 | |||
| 102 | /* ATAPI-4 UDMA specs (in clocks) */ | ||
| 103 | struct udmaspec { | ||
| 104 | u32 tcyc; | ||
| 105 | u32 t2cyc; | ||
| 106 | u32 tds; | ||
| 107 | u32 tdh; | ||
| 108 | u32 tdvs; | ||
| 109 | u32 tdvh; | ||
| 110 | u32 tfs; | ||
| 111 | u32 tli; | ||
| 112 | u32 tmli; | ||
| 113 | u32 taz; | ||
| 114 | u32 tzah; | ||
| 115 | u32 tenv; | ||
| 116 | u32 tsr; | ||
| 117 | u32 trfs; | ||
| 118 | u32 trp; | ||
| 119 | u32 tack; | ||
| 120 | u32 tss; | ||
| 121 | }; | ||
| 122 | |||
| 123 | static const struct udmaspec udmaspec66[6] = { | ||
| 124 | { .tcyc = 8, .t2cyc = 16, .tds = 1, .tdh = 1, .tdvs = 5, .tdvh = 1, | ||
| 125 | .tfs = 16, .tli = 10, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
| 126 | .tsr = 3, .trfs = 5, .trp = 11, .tack = 2, .tss = 4, | ||
| 127 | }, | ||
| 128 | { .tcyc = 5, .t2cyc = 11, .tds = 1, .tdh = 1, .tdvs = 4, .tdvh = 1, | ||
| 129 | .tfs = 14, .tli = 10, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
| 130 | .tsr = 2, .trfs = 5, .trp = 9, .tack = 2, .tss = 4, | ||
| 131 | }, | ||
| 132 | { .tcyc = 4, .t2cyc = 8, .tds = 1, .tdh = 1, .tdvs = 3, .tdvh = 1, | ||
| 133 | .tfs = 12, .tli = 10, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
| 134 | .tsr = 2, .trfs = 4, .trp = 7, .tack = 2, .tss = 4, | ||
| 135 | }, | ||
| 136 | { .tcyc = 3, .t2cyc = 6, .tds = 1, .tdh = 1, .tdvs = 2, .tdvh = 1, | ||
| 137 | .tfs = 9, .tli = 7, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
| 138 | .tsr = 2, .trfs = 4, .trp = 7, .tack = 2, .tss = 4, | ||
| 139 | }, | ||
| 140 | { .tcyc = 2, .t2cyc = 4, .tds = 1, .tdh = 1, .tdvs = 1, .tdvh = 1, | ||
| 141 | .tfs = 8, .tli = 8, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
| 142 | .tsr = 2, .trfs = 4, .trp = 7, .tack = 2, .tss = 4, | ||
| 143 | }, | ||
| 144 | { .tcyc = 2, .t2cyc = 2, .tds = 1, .tdh = 1, .tdvs = 1, .tdvh = 1, | ||
| 145 | .tfs = 6, .tli = 5, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
| 146 | .tsr = 2, .trfs = 4, .trp = 6, .tack = 2, .tss = 4, | ||
| 147 | }, | ||
| 148 | }; | ||
| 149 | |||
| 150 | static const struct udmaspec udmaspec132[6] = { | ||
| 151 | { .tcyc = 15, .t2cyc = 31, .tds = 2, .tdh = 1, .tdvs = 10, .tdvh = 1, | ||
| 152 | .tfs = 30, .tli = 20, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3, | ||
| 153 | .tsr = 7, .trfs = 10, .trp = 22, .tack = 3, .tss = 7, | ||
| 154 | }, | ||
| 155 | { .tcyc = 10, .t2cyc = 21, .tds = 2, .tdh = 1, .tdvs = 7, .tdvh = 1, | ||
| 156 | .tfs = 27, .tli = 20, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3, | ||
| 157 | .tsr = 4, .trfs = 10, .trp = 17, .tack = 3, .tss = 7, | ||
| 158 | }, | ||
| 159 | { .tcyc = 6, .t2cyc = 12, .tds = 1, .tdh = 1, .tdvs = 5, .tdvh = 1, | ||
| 160 | .tfs = 23, .tli = 20, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3, | ||
| 161 | .tsr = 3, .trfs = 8, .trp = 14, .tack = 3, .tss = 7, | ||
| 162 | }, | ||
| 163 | { .tcyc = 7, .t2cyc = 12, .tds = 1, .tdh = 1, .tdvs = 3, .tdvh = 1, | ||
| 164 | .tfs = 15, .tli = 13, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3, | ||
| 165 | .tsr = 3, .trfs = 8, .trp = 14, .tack = 3, .tss = 7, | ||
| 166 | }, | ||
| 167 | { .tcyc = 2, .t2cyc = 5, .tds = 0, .tdh = 0, .tdvs = 1, .tdvh = 1, | ||
| 168 | .tfs = 16, .tli = 14, .tmli = 2, .taz = 1, .tzah = 2, .tenv = 2, | ||
| 169 | .tsr = 2, .trfs = 7, .trp = 13, .tack = 2, .tss = 6, | ||
| 170 | }, | ||
| 171 | { .tcyc = 3, .t2cyc = 6, .tds = 1, .tdh = 1, .tdvs = 1, .tdvh = 1, | ||
| 172 | .tfs = 12, .tli = 10, .tmli = 3, .taz = 2, .tzah = 3, .tenv = 3, | ||
| 173 | .tsr = 3, .trfs = 7, .trp = 12, .tack = 3, .tss = 7, | ||
| 174 | }, | ||
| 175 | }; | ||
| 176 | |||
| 177 | /* ======================================================================== */ | ||
| 56 | 178 | ||
| 57 | /* Bit definitions inside the registers */ | 179 | /* Bit definitions inside the registers */ |
| 58 | #define MPC52xx_ATA_HOSTCONF_SMR 0x80000000UL /* State machine reset */ | 180 | #define MPC52xx_ATA_HOSTCONF_SMR 0x80000000UL /* State machine reset */ |
| @@ -66,6 +188,7 @@ static const int ataspec_ta[5] = { 35, 35, 35, 35, 35}; | |||
| 66 | #define MPC52xx_ATA_HOSTSTAT_WERR 0x01000000UL /* Write Error */ | 188 | #define MPC52xx_ATA_HOSTSTAT_WERR 0x01000000UL /* Write Error */ |
| 67 | 189 | ||
| 68 | #define MPC52xx_ATA_FIFOSTAT_EMPTY 0x01 /* FIFO Empty */ | 190 | #define MPC52xx_ATA_FIFOSTAT_EMPTY 0x01 /* FIFO Empty */ |
| 191 | #define MPC52xx_ATA_FIFOSTAT_ERROR 0x40 /* FIFO Error */ | ||
| 69 | 192 | ||
| 70 | #define MPC52xx_ATA_DMAMODE_WRITE 0x01 /* Write DMA */ | 193 | #define MPC52xx_ATA_DMAMODE_WRITE 0x01 /* Write DMA */ |
| 71 | #define MPC52xx_ATA_DMAMODE_READ 0x02 /* Read DMA */ | 194 | #define MPC52xx_ATA_DMAMODE_READ 0x02 /* Read DMA */ |
| @@ -75,6 +198,8 @@ static const int ataspec_ta[5] = { 35, 35, 35, 35, 35}; | |||
| 75 | #define MPC52xx_ATA_DMAMODE_FR 0x20 /* FIFO Reset */ | 198 | #define MPC52xx_ATA_DMAMODE_FR 0x20 /* FIFO Reset */ |
| 76 | #define MPC52xx_ATA_DMAMODE_HUT 0x40 /* Host UDMA burst terminate */ | 199 | #define MPC52xx_ATA_DMAMODE_HUT 0x40 /* Host UDMA burst terminate */ |
| 77 | 200 | ||
| 201 | #define MAX_DMA_BUFFERS 128 | ||
| 202 | #define MAX_DMA_BUFFER_SIZE 0x20000u | ||
| 78 | 203 | ||
| 79 | /* Structure of the hardware registers */ | 204 | /* Structure of the hardware registers */ |
| 80 | struct mpc52xx_ata { | 205 | struct mpc52xx_ata { |
| @@ -140,7 +265,6 @@ struct mpc52xx_ata { | |||
| 140 | 265 | ||
| 141 | 266 | ||
| 142 | /* MPC52xx low level hw control */ | 267 | /* MPC52xx low level hw control */ |
| 143 | |||
| 144 | static int | 268 | static int |
| 145 | mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio) | 269 | mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio) |
| 146 | { | 270 | { |
| @@ -148,7 +272,7 @@ mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio) | |||
| 148 | unsigned int ipb_period = priv->ipb_period; | 272 | unsigned int ipb_period = priv->ipb_period; |
| 149 | unsigned int t0, t1, t2_8, t2_16, t2i, t4, ta; | 273 | unsigned int t0, t1, t2_8, t2_16, t2i, t4, ta; |
| 150 | 274 | ||
| 151 | if ((pio<0) || (pio>4)) | 275 | if ((pio < 0) || (pio > 4)) |
| 152 | return -EINVAL; | 276 | return -EINVAL; |
| 153 | 277 | ||
| 154 | t0 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t0[pio]); | 278 | t0 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t0[pio]); |
| @@ -165,6 +289,43 @@ mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio) | |||
| 165 | return 0; | 289 | return 0; |
| 166 | } | 290 | } |
| 167 | 291 | ||
| 292 | static int | ||
| 293 | mpc52xx_ata_compute_mdma_timings(struct mpc52xx_ata_priv *priv, int dev, | ||
| 294 | int speed) | ||
| 295 | { | ||
| 296 | struct mpc52xx_ata_timings *t = &priv->timings[dev]; | ||
| 297 | const struct mdmaspec *s = &priv->mdmaspec[speed]; | ||
| 298 | |||
| 299 | if (speed < 0 || speed > 2) | ||
| 300 | return -EINVAL; | ||
| 301 | |||
| 302 | t->mdma1 = (s->t0M << 24) | (s->td << 16) | (s->tkw << 8) | (s->tm); | ||
| 303 | t->mdma2 = (s->th << 24) | (s->tj << 16) | (s->tn << 8); | ||
| 304 | t->using_udma = 0; | ||
| 305 | |||
| 306 | return 0; | ||
| 307 | } | ||
| 308 | |||
| 309 | static int | ||
| 310 | mpc52xx_ata_compute_udma_timings(struct mpc52xx_ata_priv *priv, int dev, | ||
| 311 | int speed) | ||
| 312 | { | ||
| 313 | struct mpc52xx_ata_timings *t = &priv->timings[dev]; | ||
| 314 | const struct udmaspec *s = &priv->udmaspec[speed]; | ||
| 315 | |||
| 316 | if (speed < 0 || speed > 2) | ||
| 317 | return -EINVAL; | ||
| 318 | |||
| 319 | t->udma1 = (s->t2cyc << 24) | (s->tcyc << 16) | (s->tds << 8) | s->tdh; | ||
| 320 | t->udma2 = (s->tdvs << 24) | (s->tdvh << 16) | (s->tfs << 8) | s->tli; | ||
| 321 | t->udma3 = (s->tmli << 24) | (s->taz << 16) | (s->tenv << 8) | s->tsr; | ||
| 322 | t->udma4 = (s->tss << 24) | (s->trfs << 16) | (s->trp << 8) | s->tack; | ||
| 323 | t->udma5 = (s->tzah << 24); | ||
| 324 | t->using_udma = 1; | ||
| 325 | |||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | |||
| 168 | static void | 329 | static void |
| 169 | mpc52xx_ata_apply_timings(struct mpc52xx_ata_priv *priv, int device) | 330 | mpc52xx_ata_apply_timings(struct mpc52xx_ata_priv *priv, int device) |
| 170 | { | 331 | { |
| @@ -173,14 +334,13 @@ mpc52xx_ata_apply_timings(struct mpc52xx_ata_priv *priv, int device) | |||
| 173 | 334 | ||
| 174 | out_be32(®s->pio1, timing->pio1); | 335 | out_be32(®s->pio1, timing->pio1); |
| 175 | out_be32(®s->pio2, timing->pio2); | 336 | out_be32(®s->pio2, timing->pio2); |
| 176 | out_be32(®s->mdma1, 0); | 337 | out_be32(®s->mdma1, timing->mdma1); |
| 177 | out_be32(®s->mdma2, 0); | 338 | out_be32(®s->mdma2, timing->mdma2); |
| 178 | out_be32(®s->udma1, 0); | 339 | out_be32(®s->udma1, timing->udma1); |
| 179 | out_be32(®s->udma2, 0); | 340 | out_be32(®s->udma2, timing->udma2); |
| 180 | out_be32(®s->udma3, 0); | 341 | out_be32(®s->udma3, timing->udma3); |
| 181 | out_be32(®s->udma4, 0); | 342 | out_be32(®s->udma4, timing->udma4); |
| 182 | out_be32(®s->udma5, 0); | 343 | out_be32(®s->udma5, timing->udma5); |
| 183 | |||
| 184 | priv->csel = device; | 344 | priv->csel = device; |
| 185 | } | 345 | } |
| 186 | 346 | ||
| @@ -208,7 +368,7 @@ mpc52xx_ata_hw_init(struct mpc52xx_ata_priv *priv) | |||
| 208 | 368 | ||
| 209 | /* Set the time slot to 1us */ | 369 | /* Set the time slot to 1us */ |
| 210 | tslot = CALC_CLKCYC(priv->ipb_period, 1000000); | 370 | tslot = CALC_CLKCYC(priv->ipb_period, 1000000); |
| 211 | out_be32(®s->share_cnt, tslot << 16 ); | 371 | out_be32(®s->share_cnt, tslot << 16); |
| 212 | 372 | ||
| 213 | /* Init timings to PIO0 */ | 373 | /* Init timings to PIO0 */ |
| 214 | memset(priv->timings, 0x00, 2*sizeof(struct mpc52xx_ata_timings)); | 374 | memset(priv->timings, 0x00, 2*sizeof(struct mpc52xx_ata_timings)); |
| @@ -237,13 +397,37 @@ mpc52xx_ata_set_piomode(struct ata_port *ap, struct ata_device *adev) | |||
| 237 | rv = mpc52xx_ata_compute_pio_timings(priv, adev->devno, pio); | 397 | rv = mpc52xx_ata_compute_pio_timings(priv, adev->devno, pio); |
| 238 | 398 | ||
| 239 | if (rv) { | 399 | if (rv) { |
| 240 | printk(KERN_ERR DRV_NAME | 400 | dev_err(ap->dev, "error: invalid PIO mode: %d\n", pio); |
| 241 | ": Trying to select invalid PIO mode %d\n", pio); | 401 | return; |
| 402 | } | ||
| 403 | |||
| 404 | mpc52xx_ata_apply_timings(priv, adev->devno); | ||
| 405 | } | ||
| 406 | |||
| 407 | static void | ||
| 408 | mpc52xx_ata_set_dmamode(struct ata_port *ap, struct ata_device *adev) | ||
| 409 | { | ||
| 410 | struct mpc52xx_ata_priv *priv = ap->host->private_data; | ||
| 411 | int rv; | ||
| 412 | |||
| 413 | if (adev->dma_mode >= XFER_UDMA_0) { | ||
| 414 | int dma = adev->dma_mode - XFER_UDMA_0; | ||
| 415 | rv = mpc52xx_ata_compute_udma_timings(priv, adev->devno, dma); | ||
| 416 | } else { | ||
| 417 | int dma = adev->dma_mode - XFER_MW_DMA_0; | ||
| 418 | rv = mpc52xx_ata_compute_mdma_timings(priv, adev->devno, dma); | ||
| 419 | } | ||
| 420 | |||
| 421 | if (rv) { | ||
| 422 | dev_alert(ap->dev, | ||
| 423 | "Trying to select invalid DMA mode %d\n", | ||
| 424 | adev->dma_mode); | ||
| 242 | return; | 425 | return; |
| 243 | } | 426 | } |
| 244 | 427 | ||
| 245 | mpc52xx_ata_apply_timings(priv, adev->devno); | 428 | mpc52xx_ata_apply_timings(priv, adev->devno); |
| 246 | } | 429 | } |
| 430 | |||
| 247 | static void | 431 | static void |
| 248 | mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device) | 432 | mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device) |
| 249 | { | 433 | { |
| @@ -252,7 +436,173 @@ mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device) | |||
| 252 | if (device != priv->csel) | 436 | if (device != priv->csel) |
| 253 | mpc52xx_ata_apply_timings(priv, device); | 437 | mpc52xx_ata_apply_timings(priv, device); |
| 254 | 438 | ||
| 255 | ata_sff_dev_select(ap,device); | 439 | ata_sff_dev_select(ap, device); |
| 440 | } | ||
| 441 | |||
| 442 | static int | ||
| 443 | mpc52xx_ata_build_dmatable(struct ata_queued_cmd *qc) | ||
| 444 | { | ||
| 445 | struct ata_port *ap = qc->ap; | ||
| 446 | struct mpc52xx_ata_priv *priv = ap->host->private_data; | ||
| 447 | struct bcom_ata_bd *bd; | ||
| 448 | unsigned int read = !(qc->tf.flags & ATA_TFLAG_WRITE), si; | ||
| 449 | struct scatterlist *sg; | ||
| 450 | int count = 0; | ||
| 451 | |||
| 452 | if (read) | ||
| 453 | bcom_ata_rx_prepare(priv->dmatsk); | ||
| 454 | else | ||
| 455 | bcom_ata_tx_prepare(priv->dmatsk); | ||
| 456 | |||
| 457 | for_each_sg(qc->sg, sg, qc->n_elem, si) { | ||
| 458 | dma_addr_t cur_addr = sg_dma_address(sg); | ||
| 459 | u32 cur_len = sg_dma_len(sg); | ||
| 460 | |||
| 461 | while (cur_len) { | ||
| 462 | unsigned int tc = min(cur_len, MAX_DMA_BUFFER_SIZE); | ||
| 463 | bd = (struct bcom_ata_bd *) | ||
| 464 | bcom_prepare_next_buffer(priv->dmatsk); | ||
| 465 | |||
| 466 | if (read) { | ||
| 467 | bd->status = tc; | ||
| 468 | bd->src_pa = (__force u32) priv->ata_regs_pa + | ||
| 469 | offsetof(struct mpc52xx_ata, fifo_data); | ||
| 470 | bd->dst_pa = (__force u32) cur_addr; | ||
| 471 | } else { | ||
| 472 | bd->status = tc; | ||
| 473 | bd->src_pa = (__force u32) cur_addr; | ||
| 474 | bd->dst_pa = (__force u32) priv->ata_regs_pa + | ||
| 475 | offsetof(struct mpc52xx_ata, fifo_data); | ||
| 476 | } | ||
| 477 | |||
| 478 | bcom_submit_next_buffer(priv->dmatsk, NULL); | ||
| 479 | |||
| 480 | cur_addr += tc; | ||
| 481 | cur_len -= tc; | ||
| 482 | count++; | ||
| 483 | |||
| 484 | if (count > MAX_DMA_BUFFERS) { | ||
| 485 | dev_alert(ap->dev, "dma table" | ||
| 486 | "too small\n"); | ||
| 487 | goto use_pio_instead; | ||
| 488 | } | ||
| 489 | } | ||
| 490 | } | ||
| 491 | return 1; | ||
| 492 | |||
| 493 | use_pio_instead: | ||
| 494 | bcom_ata_reset_bd(priv->dmatsk); | ||
| 495 | return 0; | ||
| 496 | } | ||
| 497 | |||
| 498 | static void | ||
| 499 | mpc52xx_bmdma_setup(struct ata_queued_cmd *qc) | ||
| 500 | { | ||
| 501 | struct ata_port *ap = qc->ap; | ||
| 502 | struct mpc52xx_ata_priv *priv = ap->host->private_data; | ||
| 503 | struct mpc52xx_ata __iomem *regs = priv->ata_regs; | ||
| 504 | |||
| 505 | unsigned int read = !(qc->tf.flags & ATA_TFLAG_WRITE); | ||
| 506 | u8 dma_mode; | ||
| 507 | |||
| 508 | if (!mpc52xx_ata_build_dmatable(qc)) | ||
| 509 | dev_alert(ap->dev, "%s: %i, return 1?\n", | ||
| 510 | __func__, __LINE__); | ||
| 511 | |||
| 512 | /* Check FIFO is OK... */ | ||
| 513 | if (in_8(&priv->ata_regs->fifo_status) & MPC52xx_ATA_FIFOSTAT_ERROR) | ||
| 514 | dev_alert(ap->dev, "%s: FIFO error detected: 0x%02x!\n", | ||
| 515 | __func__, in_8(&priv->ata_regs->fifo_status)); | ||
| 516 | |||
| 517 | if (read) { | ||
| 518 | dma_mode = MPC52xx_ATA_DMAMODE_IE | MPC52xx_ATA_DMAMODE_READ | | ||
| 519 | MPC52xx_ATA_DMAMODE_FE; | ||
| 520 | |||
| 521 | /* Setup FIFO if direction changed */ | ||
| 522 | if (priv->mpc52xx_ata_dma_last_write != 0) { | ||
| 523 | priv->mpc52xx_ata_dma_last_write = 0; | ||
| 524 | |||
| 525 | /* Configure FIFO with granularity to 7 */ | ||
| 526 | out_8(®s->fifo_control, 7); | ||
| 527 | out_be16(®s->fifo_alarm, 128); | ||
| 528 | |||
| 529 | /* Set FIFO Reset bit (FR) */ | ||
| 530 | out_8(®s->dma_mode, MPC52xx_ATA_DMAMODE_FR); | ||
| 531 | } | ||
| 532 | } else { | ||
| 533 | dma_mode = MPC52xx_ATA_DMAMODE_IE | MPC52xx_ATA_DMAMODE_WRITE; | ||
| 534 | |||
| 535 | /* Setup FIFO if direction changed */ | ||
| 536 | if (priv->mpc52xx_ata_dma_last_write != 1) { | ||
| 537 | priv->mpc52xx_ata_dma_last_write = 1; | ||
| 538 | |||
| 539 | /* Configure FIFO with granularity to 4 */ | ||
| 540 | out_8(®s->fifo_control, 4); | ||
| 541 | out_be16(®s->fifo_alarm, 128); | ||
| 542 | } | ||
| 543 | } | ||
| 544 | |||
| 545 | if (priv->timings[qc->dev->devno].using_udma) | ||
| 546 | dma_mode |= MPC52xx_ATA_DMAMODE_UDMA; | ||
| 547 | |||
| 548 | out_8(®s->dma_mode, dma_mode); | ||
| 549 | priv->waiting_for_dma = ATA_DMA_ACTIVE; | ||
| 550 | |||
| 551 | ata_wait_idle(ap); | ||
| 552 | ap->ops->sff_exec_command(ap, &qc->tf); | ||
| 553 | } | ||
| 554 | |||
| 555 | static void | ||
| 556 | mpc52xx_bmdma_start(struct ata_queued_cmd *qc) | ||
| 557 | { | ||
| 558 | struct ata_port *ap = qc->ap; | ||
| 559 | struct mpc52xx_ata_priv *priv = ap->host->private_data; | ||
| 560 | |||
| 561 | bcom_set_task_auto_start(priv->dmatsk->tasknum, priv->dmatsk->tasknum); | ||
| 562 | bcom_enable(priv->dmatsk); | ||
| 563 | } | ||
| 564 | |||
| 565 | static void | ||
| 566 | mpc52xx_bmdma_stop(struct ata_queued_cmd *qc) | ||
| 567 | { | ||
| 568 | struct ata_port *ap = qc->ap; | ||
| 569 | struct mpc52xx_ata_priv *priv = ap->host->private_data; | ||
| 570 | |||
| 571 | bcom_disable(priv->dmatsk); | ||
| 572 | bcom_ata_reset_bd(priv->dmatsk); | ||
| 573 | priv->waiting_for_dma = 0; | ||
| 574 | |||
| 575 | /* Check FIFO is OK... */ | ||
| 576 | if (in_8(&priv->ata_regs->fifo_status) & MPC52xx_ATA_FIFOSTAT_ERROR) | ||
| 577 | dev_alert(ap->dev, "%s: FIFO error detected: 0x%02x!\n", | ||
| 578 | __func__, in_8(&priv->ata_regs->fifo_status)); | ||
| 579 | } | ||
| 580 | |||
| 581 | static u8 | ||
| 582 | mpc52xx_bmdma_status(struct ata_port *ap) | ||
| 583 | { | ||
| 584 | struct mpc52xx_ata_priv *priv = ap->host->private_data; | ||
| 585 | |||
| 586 | /* Check FIFO is OK... */ | ||
| 587 | if (in_8(&priv->ata_regs->fifo_status) & MPC52xx_ATA_FIFOSTAT_ERROR) { | ||
| 588 | dev_alert(ap->dev, "%s: FIFO error detected: 0x%02x!\n", | ||
| 589 | __func__, in_8(&priv->ata_regs->fifo_status)); | ||
| 590 | return priv->waiting_for_dma | ATA_DMA_ERR; | ||
| 591 | } | ||
| 592 | |||
| 593 | return priv->waiting_for_dma; | ||
| 594 | } | ||
| 595 | |||
| 596 | static irqreturn_t | ||
| 597 | mpc52xx_ata_task_irq(int irq, void *vpriv) | ||
| 598 | { | ||
| 599 | struct mpc52xx_ata_priv *priv = vpriv; | ||
| 600 | while (bcom_buffer_done(priv->dmatsk)) | ||
| 601 | bcom_retrieve_buffer(priv->dmatsk, NULL, NULL); | ||
| 602 | |||
| 603 | priv->waiting_for_dma |= ATA_DMA_INTR; | ||
| 604 | |||
| 605 | return IRQ_HANDLED; | ||
| 256 | } | 606 | } |
| 257 | 607 | ||
| 258 | static struct scsi_host_template mpc52xx_ata_sht = { | 608 | static struct scsi_host_template mpc52xx_ata_sht = { |
| @@ -262,14 +612,18 @@ static struct scsi_host_template mpc52xx_ata_sht = { | |||
| 262 | static struct ata_port_operations mpc52xx_ata_port_ops = { | 612 | static struct ata_port_operations mpc52xx_ata_port_ops = { |
| 263 | .inherits = &ata_sff_port_ops, | 613 | .inherits = &ata_sff_port_ops, |
| 264 | .sff_dev_select = mpc52xx_ata_dev_select, | 614 | .sff_dev_select = mpc52xx_ata_dev_select, |
| 265 | .cable_detect = ata_cable_40wire, | ||
| 266 | .set_piomode = mpc52xx_ata_set_piomode, | 615 | .set_piomode = mpc52xx_ata_set_piomode, |
| 267 | .post_internal_cmd = ATA_OP_NULL, | 616 | .set_dmamode = mpc52xx_ata_set_dmamode, |
| 617 | .bmdma_setup = mpc52xx_bmdma_setup, | ||
| 618 | .bmdma_start = mpc52xx_bmdma_start, | ||
| 619 | .bmdma_stop = mpc52xx_bmdma_stop, | ||
| 620 | .bmdma_status = mpc52xx_bmdma_status, | ||
| 621 | .qc_prep = ata_noop_qc_prep, | ||
| 268 | }; | 622 | }; |
| 269 | 623 | ||
| 270 | static int __devinit | 624 | static int __devinit |
| 271 | mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv, | 625 | mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv, |
| 272 | unsigned long raw_ata_regs) | 626 | unsigned long raw_ata_regs, int mwdma_mask, int udma_mask) |
| 273 | { | 627 | { |
| 274 | struct ata_host *host; | 628 | struct ata_host *host; |
| 275 | struct ata_port *ap; | 629 | struct ata_port *ap; |
| @@ -281,9 +635,9 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv, | |||
| 281 | 635 | ||
| 282 | ap = host->ports[0]; | 636 | ap = host->ports[0]; |
| 283 | ap->flags |= ATA_FLAG_SLAVE_POSS; | 637 | ap->flags |= ATA_FLAG_SLAVE_POSS; |
| 284 | ap->pio_mask = 0x1f; /* Up to PIO4 */ | 638 | ap->pio_mask = ATA_PIO4; |
| 285 | ap->mwdma_mask = 0x00; /* No MWDMA */ | 639 | ap->mwdma_mask = mwdma_mask; |
| 286 | ap->udma_mask = 0x00; /* No UDMA */ | 640 | ap->udma_mask = udma_mask; |
| 287 | ap->ops = &mpc52xx_ata_port_ops; | 641 | ap->ops = &mpc52xx_ata_port_ops; |
| 288 | host->private_data = priv; | 642 | host->private_data = priv; |
| 289 | 643 | ||
| @@ -330,89 +684,139 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match) | |||
| 330 | { | 684 | { |
| 331 | unsigned int ipb_freq; | 685 | unsigned int ipb_freq; |
| 332 | struct resource res_mem; | 686 | struct resource res_mem; |
| 333 | int ata_irq; | 687 | int ata_irq = 0; |
| 334 | struct mpc52xx_ata __iomem *ata_regs; | 688 | struct mpc52xx_ata __iomem *ata_regs; |
| 335 | struct mpc52xx_ata_priv *priv; | 689 | struct mpc52xx_ata_priv *priv = NULL; |
| 336 | int rv; | 690 | int rv, ret, task_irq = 0; |
| 691 | int mwdma_mask = 0, udma_mask = 0; | ||
| 692 | const __be32 *prop; | ||
| 693 | int proplen; | ||
| 694 | struct bcom_task *dmatsk = NULL; | ||
| 337 | 695 | ||
| 338 | /* Get ipb frequency */ | 696 | /* Get ipb frequency */ |
| 339 | ipb_freq = mpc52xx_find_ipb_freq(op->node); | 697 | ipb_freq = mpc52xx_find_ipb_freq(op->node); |
| 340 | if (!ipb_freq) { | 698 | if (!ipb_freq) { |
| 341 | printk(KERN_ERR DRV_NAME ": " | 699 | dev_err(&op->dev, "could not determine IPB bus frequency\n"); |
| 342 | "Unable to find IPB Bus frequency\n" ); | ||
| 343 | return -ENODEV; | 700 | return -ENODEV; |
| 344 | } | 701 | } |
| 345 | 702 | ||
| 346 | /* Get IRQ and register */ | 703 | /* Get device base address from device tree, request the region |
| 704 | * and ioremap it. */ | ||
| 347 | rv = of_address_to_resource(op->node, 0, &res_mem); | 705 | rv = of_address_to_resource(op->node, 0, &res_mem); |
| 348 | if (rv) { | 706 | if (rv) { |
| 349 | printk(KERN_ERR DRV_NAME ": " | 707 | dev_err(&op->dev, "could not determine device base address\n"); |
| 350 | "Error while parsing device node resource\n" ); | ||
| 351 | return rv; | 708 | return rv; |
| 352 | } | 709 | } |
| 353 | 710 | ||
| 354 | ata_irq = irq_of_parse_and_map(op->node, 0); | ||
| 355 | if (ata_irq == NO_IRQ) { | ||
| 356 | printk(KERN_ERR DRV_NAME ": " | ||
| 357 | "Error while mapping the irq\n"); | ||
| 358 | return -EINVAL; | ||
| 359 | } | ||
| 360 | |||
| 361 | /* Request mem region */ | ||
| 362 | if (!devm_request_mem_region(&op->dev, res_mem.start, | 711 | if (!devm_request_mem_region(&op->dev, res_mem.start, |
| 363 | sizeof(struct mpc52xx_ata), DRV_NAME)) { | 712 | sizeof(*ata_regs), DRV_NAME)) { |
| 364 | printk(KERN_ERR DRV_NAME ": " | 713 | dev_err(&op->dev, "error requesting register region\n"); |
| 365 | "Error while requesting mem region\n"); | 714 | return -EBUSY; |
| 366 | rv = -EBUSY; | ||
| 367 | goto err; | ||
| 368 | } | 715 | } |
| 369 | 716 | ||
| 370 | /* Remap registers */ | 717 | ata_regs = devm_ioremap(&op->dev, res_mem.start, sizeof(*ata_regs)); |
| 371 | ata_regs = devm_ioremap(&op->dev, res_mem.start, | ||
| 372 | sizeof(struct mpc52xx_ata)); | ||
| 373 | if (!ata_regs) { | 718 | if (!ata_regs) { |
| 374 | printk(KERN_ERR DRV_NAME ": " | 719 | dev_err(&op->dev, "error mapping device registers\n"); |
| 375 | "Error while mapping register set\n"); | ||
| 376 | rv = -ENOMEM; | 720 | rv = -ENOMEM; |
| 377 | goto err; | 721 | goto err; |
| 378 | } | 722 | } |
| 379 | 723 | ||
| 724 | /* | ||
| 725 | * By default, all DMA modes are disabled for the MPC5200. Some | ||
| 726 | * boards don't have the required signals routed to make DMA work. | ||
| 727 | * Also, the MPC5200B has a silicon bug that causes data corruption | ||
| 728 | * with UDMA if it is used at the same time as the LocalPlus bus. | ||
| 729 | * | ||
| 730 | * Instead of trying to guess what modes are usable, check the | ||
| 731 | * ATA device tree node to find out what DMA modes work on the board. | ||
| 732 | * UDMA/MWDMA modes can also be forced by adding "libata.force=<mode>" | ||
| 733 | * to the kernel boot parameters. | ||
| 734 | * | ||
| 735 | * The MPC5200 ATA controller supports MWDMA modes 0, 1 and 2 and | ||
| 736 | * UDMA modes 0, 1 and 2. | ||
| 737 | */ | ||
| 738 | prop = of_get_property(op->node, "mwdma-mode", &proplen); | ||
| 739 | if ((prop) && (proplen >= 4)) | ||
| 740 | mwdma_mask = 0x7 & ((1 << (*prop + 1)) - 1); | ||
| 741 | prop = of_get_property(op->node, "udma-mode", &proplen); | ||
| 742 | if ((prop) && (proplen >= 4)) | ||
| 743 | udma_mask = 0x7 & ((1 << (*prop + 1)) - 1); | ||
| 744 | |||
| 745 | ata_irq = irq_of_parse_and_map(op->node, 0); | ||
| 746 | if (ata_irq == NO_IRQ) { | ||
| 747 | dev_err(&op->dev, "error mapping irq\n"); | ||
| 748 | return -EINVAL; | ||
| 749 | } | ||
| 750 | |||
| 380 | /* Prepare our private structure */ | 751 | /* Prepare our private structure */ |
| 381 | priv = devm_kzalloc(&op->dev, sizeof(struct mpc52xx_ata_priv), | 752 | priv = devm_kzalloc(&op->dev, sizeof(*priv), GFP_ATOMIC); |
| 382 | GFP_ATOMIC); | ||
| 383 | if (!priv) { | 753 | if (!priv) { |
| 384 | printk(KERN_ERR DRV_NAME ": " | 754 | dev_err(&op->dev, "error allocating private structure\n"); |
| 385 | "Error while allocating private structure\n"); | ||
| 386 | rv = -ENOMEM; | 755 | rv = -ENOMEM; |
| 387 | goto err; | 756 | goto err; |
| 388 | } | 757 | } |
| 389 | 758 | ||
| 390 | priv->ipb_period = 1000000000 / (ipb_freq / 1000); | 759 | priv->ipb_period = 1000000000 / (ipb_freq / 1000); |
| 391 | priv->ata_regs = ata_regs; | 760 | priv->ata_regs = ata_regs; |
| 761 | priv->ata_regs_pa = res_mem.start; | ||
| 392 | priv->ata_irq = ata_irq; | 762 | priv->ata_irq = ata_irq; |
| 393 | priv->csel = -1; | 763 | priv->csel = -1; |
| 764 | priv->mpc52xx_ata_dma_last_write = -1; | ||
| 765 | |||
| 766 | if (ipb_freq/1000000 == 66) { | ||
| 767 | priv->mdmaspec = mdmaspec66; | ||
| 768 | priv->udmaspec = udmaspec66; | ||
| 769 | } else { | ||
| 770 | priv->mdmaspec = mdmaspec132; | ||
| 771 | priv->udmaspec = udmaspec132; | ||
| 772 | } | ||
| 773 | |||
| 774 | /* Allocate a BestComm task for DMA */ | ||
| 775 | dmatsk = bcom_ata_init(MAX_DMA_BUFFERS, MAX_DMA_BUFFER_SIZE); | ||
| 776 | if (!dmatsk) { | ||
| 777 | dev_err(&op->dev, "bestcomm initialization failed\n"); | ||
| 778 | rv = -ENOMEM; | ||
| 779 | goto err; | ||
| 780 | } | ||
| 781 | |||
| 782 | task_irq = bcom_get_task_irq(dmatsk); | ||
| 783 | ret = request_irq(task_irq, &mpc52xx_ata_task_irq, IRQF_DISABLED, | ||
| 784 | "ATA task", priv); | ||
| 785 | if (ret) { | ||
| 786 | dev_err(&op->dev, "error requesting DMA IRQ\n"); | ||
| 787 | goto err; | ||
| 788 | } | ||
| 789 | priv->dmatsk = dmatsk; | ||
| 394 | 790 | ||
| 395 | /* Init the hw */ | 791 | /* Init the hw */ |
| 396 | rv = mpc52xx_ata_hw_init(priv); | 792 | rv = mpc52xx_ata_hw_init(priv); |
| 397 | if (rv) { | 793 | if (rv) { |
| 398 | printk(KERN_ERR DRV_NAME ": Error during HW init\n"); | 794 | dev_err(&op->dev, "error initializing hardware\n"); |
| 399 | goto err; | 795 | goto err; |
| 400 | } | 796 | } |
| 401 | 797 | ||
| 402 | /* Register ourselves to libata */ | 798 | /* Register ourselves to libata */ |
| 403 | rv = mpc52xx_ata_init_one(&op->dev, priv, res_mem.start); | 799 | rv = mpc52xx_ata_init_one(&op->dev, priv, res_mem.start, |
| 800 | mwdma_mask, udma_mask); | ||
| 404 | if (rv) { | 801 | if (rv) { |
| 405 | printk(KERN_ERR DRV_NAME ": " | 802 | dev_err(&op->dev, "error registering with ATA layer\n"); |
| 406 | "Error while registering to ATA layer\n"); | 803 | goto err; |
| 407 | return rv; | ||
| 408 | } | 804 | } |
| 409 | 805 | ||
| 410 | /* Done */ | ||
| 411 | return 0; | 806 | return 0; |
| 412 | 807 | ||
| 413 | /* Error path */ | 808 | err: |
| 414 | err: | 809 | devm_release_mem_region(&op->dev, res_mem.start, sizeof(*ata_regs)); |
| 415 | irq_dispose_mapping(ata_irq); | 810 | if (ata_irq) |
| 811 | irq_dispose_mapping(ata_irq); | ||
| 812 | if (task_irq) | ||
| 813 | irq_dispose_mapping(task_irq); | ||
| 814 | if (dmatsk) | ||
| 815 | bcom_ata_release(dmatsk); | ||
| 816 | if (ata_regs) | ||
| 817 | devm_iounmap(&op->dev, ata_regs); | ||
| 818 | if (priv) | ||
| 819 | devm_kfree(&op->dev, priv); | ||
| 416 | return rv; | 820 | return rv; |
| 417 | } | 821 | } |
| 418 | 822 | ||
| @@ -420,10 +824,23 @@ static int | |||
| 420 | mpc52xx_ata_remove(struct of_device *op) | 824 | mpc52xx_ata_remove(struct of_device *op) |
| 421 | { | 825 | { |
| 422 | struct mpc52xx_ata_priv *priv; | 826 | struct mpc52xx_ata_priv *priv; |
| 827 | int task_irq; | ||
| 423 | 828 | ||
| 829 | /* Deregister the ATA interface */ | ||
| 424 | priv = mpc52xx_ata_remove_one(&op->dev); | 830 | priv = mpc52xx_ata_remove_one(&op->dev); |
| 831 | |||
| 832 | /* Clean up DMA */ | ||
| 833 | task_irq = bcom_get_task_irq(priv->dmatsk); | ||
| 834 | irq_dispose_mapping(task_irq); | ||
| 835 | bcom_ata_release(priv->dmatsk); | ||
| 425 | irq_dispose_mapping(priv->ata_irq); | 836 | irq_dispose_mapping(priv->ata_irq); |
| 426 | 837 | ||
| 838 | /* Clear up IO allocations */ | ||
| 839 | devm_iounmap(&op->dev, priv->ata_regs); | ||
| 840 | devm_release_mem_region(&op->dev, priv->ata_regs_pa, | ||
| 841 | sizeof(*priv->ata_regs)); | ||
| 842 | devm_kfree(&op->dev, priv); | ||
| 843 | |||
| 427 | return 0; | 844 | return 0; |
| 428 | } | 845 | } |
| 429 | 846 | ||
| @@ -447,7 +864,7 @@ mpc52xx_ata_resume(struct of_device *op) | |||
| 447 | 864 | ||
| 448 | rv = mpc52xx_ata_hw_init(priv); | 865 | rv = mpc52xx_ata_hw_init(priv); |
| 449 | if (rv) { | 866 | if (rv) { |
| 450 | printk(KERN_ERR DRV_NAME ": Error during HW init\n"); | 867 | dev_err(host->dev, "error initializing hardware\n"); |
| 451 | return rv; | 868 | return rv; |
| 452 | } | 869 | } |
| 453 | 870 | ||
| @@ -507,5 +924,4 @@ MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>"); | |||
| 507 | MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA libata driver"); | 924 | MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA libata driver"); |
| 508 | MODULE_LICENSE("GPL"); | 925 | MODULE_LICENSE("GPL"); |
| 509 | MODULE_DEVICE_TABLE(of, mpc52xx_ata_of_match); | 926 | MODULE_DEVICE_TABLE(of, mpc52xx_ata_of_match); |
| 510 | MODULE_VERSION(DRV_VERSION); | ||
| 511 | 927 | ||
