Linus Walleij | be4e456 | 2017-06-04 10:50:08 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Faraday Technology FTIDE010 driver |
| 3 | * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> |
| 4 | * |
| 5 | * Includes portions of the SL2312/SL3516/Gemini PATA driver |
| 6 | * Copyright (C) 2003 StorLine, Inc <jason@storlink.com.tw> |
| 7 | * Copyright (C) 2009 Janos Laube <janos.dev@gmail.com> |
| 8 | * Copyright (C) 2010 Frederic Pecourt <opengemini@free.fr> |
| 9 | * Copyright (C) 2011 Tobias Waldvogel <tobias.waldvogel@gmail.com> |
| 10 | */ |
| 11 | |
| 12 | #include <linux/platform_device.h> |
| 13 | #include <linux/module.h> |
| 14 | #include <linux/libata.h> |
| 15 | #include <linux/bitops.h> |
| 16 | #include <linux/of_address.h> |
| 17 | #include <linux/of_device.h> |
| 18 | #include <linux/clk.h> |
| 19 | #include "sata_gemini.h" |
| 20 | |
| 21 | #define DRV_NAME "pata_ftide010" |
| 22 | |
| 23 | /** |
| 24 | * struct ftide010 - state container for the Faraday FTIDE010 |
| 25 | * @dev: pointer back to the device representing this controller |
| 26 | * @base: remapped I/O space address |
| 27 | * @pclk: peripheral clock for the IDE block |
| 28 | * @host: pointer to the ATA host for this device |
| 29 | * @master_cbl: master cable type |
| 30 | * @slave_cbl: slave cable type |
| 31 | * @sg: Gemini SATA bridge pointer, if running on the Gemini |
| 32 | * @master_to_sata0: Gemini SATA bridge: the ATA master is connected |
| 33 | * to the SATA0 bridge |
| 34 | * @slave_to_sata0: Gemini SATA bridge: the ATA slave is connected |
| 35 | * to the SATA0 bridge |
| 36 | * @master_to_sata1: Gemini SATA bridge: the ATA master is connected |
| 37 | * to the SATA1 bridge |
| 38 | * @slave_to_sata1: Gemini SATA bridge: the ATA slave is connected |
| 39 | * to the SATA1 bridge |
| 40 | */ |
| 41 | struct ftide010 { |
| 42 | struct device *dev; |
| 43 | void __iomem *base; |
| 44 | struct clk *pclk; |
| 45 | struct ata_host *host; |
| 46 | unsigned int master_cbl; |
| 47 | unsigned int slave_cbl; |
| 48 | /* Gemini-specific properties */ |
| 49 | struct sata_gemini *sg; |
| 50 | bool master_to_sata0; |
| 51 | bool slave_to_sata0; |
| 52 | bool master_to_sata1; |
| 53 | bool slave_to_sata1; |
| 54 | }; |
| 55 | |
| 56 | #define FTIDE010_DMA_REG 0x00 |
| 57 | #define FTIDE010_DMA_STATUS 0x02 |
| 58 | #define FTIDE010_IDE_BMDTPR 0x04 |
| 59 | #define FTIDE010_IDE_DEVICE_ID 0x08 |
| 60 | #define FTIDE010_PIO_TIMING 0x10 |
| 61 | #define FTIDE010_MWDMA_TIMING 0x11 |
| 62 | #define FTIDE010_UDMA_TIMING0 0x12 /* Master */ |
| 63 | #define FTIDE010_UDMA_TIMING1 0x13 /* Slave */ |
| 64 | #define FTIDE010_CLK_MOD 0x14 |
| 65 | /* These registers are mapped directly to the IDE registers */ |
| 66 | #define FTIDE010_CMD_DATA 0x20 |
| 67 | #define FTIDE010_ERROR_FEATURES 0x21 |
| 68 | #define FTIDE010_NSECT 0x22 |
| 69 | #define FTIDE010_LBAL 0x23 |
| 70 | #define FTIDE010_LBAM 0x24 |
| 71 | #define FTIDE010_LBAH 0x25 |
| 72 | #define FTIDE010_DEVICE 0x26 |
| 73 | #define FTIDE010_STATUS_COMMAND 0x27 |
| 74 | #define FTIDE010_ALTSTAT_CTRL 0x36 |
| 75 | |
| 76 | /* Set this bit for UDMA mode 5 and 6 */ |
| 77 | #define FTIDE010_UDMA_TIMING_MODE_56 BIT(7) |
| 78 | |
| 79 | /* 0 = 50 MHz, 1 = 66 MHz */ |
| 80 | #define FTIDE010_CLK_MOD_DEV0_CLK_SEL BIT(0) |
| 81 | #define FTIDE010_CLK_MOD_DEV1_CLK_SEL BIT(1) |
| 82 | /* Enable UDMA on a device */ |
| 83 | #define FTIDE010_CLK_MOD_DEV0_UDMA_EN BIT(4) |
| 84 | #define FTIDE010_CLK_MOD_DEV1_UDMA_EN BIT(5) |
| 85 | |
| 86 | static struct scsi_host_template pata_ftide010_sht = { |
| 87 | ATA_BMDMA_SHT(DRV_NAME), |
| 88 | }; |
| 89 | |
| 90 | /* |
| 91 | * Bus timings |
| 92 | * |
| 93 | * The unit of the below required timings is two clock periods of the ATA |
| 94 | * reference clock which is 30 nanoseconds per unit at 66MHz and 20 |
| 95 | * nanoseconds per unit at 50 MHz. The PIO timings assume 33MHz speed for |
| 96 | * PIO. |
| 97 | * |
| 98 | * pio_active_time: array of 5 elements for T2 timing for Mode 0, |
| 99 | * 1, 2, 3 and 4. Range 0..15. |
| 100 | * pio_recovery_time: array of 5 elements for T2l timing for Mode 0, |
| 101 | * 1, 2, 3 and 4. Range 0..15. |
| 102 | * mdma_50_active_time: array of 4 elements for Td timing for multi |
| 103 | * word DMA, Mode 0, 1, and 2 at 50 MHz. Range 0..15. |
| 104 | * mdma_50_recovery_time: array of 4 elements for Tk timing for |
| 105 | * multi word DMA, Mode 0, 1 and 2 at 50 MHz. Range 0..15. |
| 106 | * mdma_66_active_time: array of 4 elements for Td timing for multi |
| 107 | * word DMA, Mode 0, 1 and 2 at 66 MHz. Range 0..15. |
| 108 | * mdma_66_recovery_time: array of 4 elements for Tk timing for |
| 109 | * multi word DMA, Mode 0, 1 and 2 at 66 MHz. Range 0..15. |
| 110 | * udma_50_setup_time: array of 4 elements for Tvds timing for ultra |
| 111 | * DMA, Mode 0, 1, 2, 3, 4 and 5 at 50 MHz. Range 0..7. |
| 112 | * udma_50_hold_time: array of 4 elements for Tdvh timing for |
| 113 | * multi word DMA, Mode 0, 1, 2, 3, 4 and 5 at 50 MHz, Range 0..7. |
| 114 | * udma_66_setup_time: array of 4 elements for Tvds timing for multi |
| 115 | * word DMA, Mode 0, 1, 2, 3, 4, 5 and 6 at 66 MHz. Range 0..7. |
| 116 | * udma_66_hold_time: array of 4 elements for Tdvh timing for |
| 117 | * multi word DMA, Mode 0, 1, 2, 3, 4, 5 and 6 at 66 MHz. Range 0..7. |
| 118 | */ |
| 119 | static const u8 pio_active_time[5] = {10, 10, 10, 3, 3}; |
| 120 | static const u8 pio_recovery_time[5] = {10, 3, 1, 3, 1}; |
| 121 | static const u8 mwdma_50_active_time[3] = {6, 2, 2}; |
| 122 | static const u8 mwdma_50_recovery_time[3] = {6, 2, 1}; |
| 123 | static const u8 mwdma_66_active_time[3] = {8, 3, 3}; |
| 124 | static const u8 mwdma_66_recovery_time[3] = {8, 2, 1}; |
| 125 | static const u8 udma_50_setup_time[6] = {3, 3, 2, 2, 1, 1}; |
| 126 | static const u8 udma_50_hold_time[6] = {3, 1, 1, 1, 1, 1}; |
| 127 | static const u8 udma_66_setup_time[7] = {4, 4, 3, 2, }; |
| 128 | static const u8 udma_66_hold_time[7] = {}; |
| 129 | |
| 130 | /* |
| 131 | * We set 66 MHz for all MWDMA modes |
| 132 | */ |
| 133 | static const bool set_mdma_66_mhz[] = { true, true, true, true }; |
| 134 | |
| 135 | /* |
| 136 | * We set 66 MHz for UDMA modes 3, 4 and 6 and no others |
| 137 | */ |
| 138 | static const bool set_udma_66_mhz[] = { false, false, false, true, true, false, true }; |
| 139 | |
| 140 | static void ftide010_set_dmamode(struct ata_port *ap, struct ata_device *adev) |
| 141 | { |
| 142 | struct ftide010 *ftide = ap->host->private_data; |
| 143 | u8 speed = adev->dma_mode; |
| 144 | u8 devno = adev->devno & 1; |
| 145 | u8 udma_en_mask; |
| 146 | u8 f66m_en_mask; |
| 147 | u8 clkreg; |
| 148 | u8 timreg; |
| 149 | u8 i; |
| 150 | |
| 151 | /* Target device 0 (master) or 1 (slave) */ |
| 152 | if (!devno) { |
| 153 | udma_en_mask = FTIDE010_CLK_MOD_DEV0_UDMA_EN; |
| 154 | f66m_en_mask = FTIDE010_CLK_MOD_DEV0_CLK_SEL; |
| 155 | } else { |
| 156 | udma_en_mask = FTIDE010_CLK_MOD_DEV1_UDMA_EN; |
| 157 | f66m_en_mask = FTIDE010_CLK_MOD_DEV1_CLK_SEL; |
| 158 | } |
| 159 | |
| 160 | clkreg = readb(ftide->base + FTIDE010_CLK_MOD); |
| 161 | clkreg &= ~udma_en_mask; |
| 162 | clkreg &= ~f66m_en_mask; |
| 163 | |
| 164 | if (speed & XFER_UDMA_0) { |
| 165 | i = speed & ~XFER_UDMA_0; |
| 166 | dev_dbg(ftide->dev, "set UDMA mode %02x, index %d\n", |
| 167 | speed, i); |
| 168 | |
| 169 | clkreg |= udma_en_mask; |
| 170 | if (set_udma_66_mhz[i]) { |
| 171 | clkreg |= f66m_en_mask; |
| 172 | timreg = udma_66_setup_time[i] << 4 | |
| 173 | udma_66_hold_time[i]; |
| 174 | } else { |
| 175 | timreg = udma_50_setup_time[i] << 4 | |
| 176 | udma_50_hold_time[i]; |
| 177 | } |
| 178 | |
| 179 | /* A special bit needs to be set for modes 5 and 6 */ |
| 180 | if (i >= 5) |
| 181 | timreg |= FTIDE010_UDMA_TIMING_MODE_56; |
| 182 | |
| 183 | dev_dbg(ftide->dev, "UDMA write clkreg = %02x, timreg = %02x\n", |
| 184 | clkreg, timreg); |
| 185 | |
| 186 | writeb(clkreg, ftide->base + FTIDE010_CLK_MOD); |
| 187 | writeb(timreg, ftide->base + FTIDE010_UDMA_TIMING0 + devno); |
| 188 | } else { |
| 189 | i = speed & ~XFER_MW_DMA_0; |
| 190 | dev_dbg(ftide->dev, "set MWDMA mode %02x, index %d\n", |
| 191 | speed, i); |
| 192 | |
| 193 | if (set_mdma_66_mhz[i]) { |
| 194 | clkreg |= f66m_en_mask; |
| 195 | timreg = mwdma_66_active_time[i] << 4 | |
| 196 | mwdma_66_recovery_time[i]; |
| 197 | } else { |
| 198 | timreg = mwdma_50_active_time[i] << 4 | |
| 199 | mwdma_50_recovery_time[i]; |
| 200 | } |
| 201 | dev_dbg(ftide->dev, |
| 202 | "MWDMA write clkreg = %02x, timreg = %02x\n", |
| 203 | clkreg, timreg); |
| 204 | /* This will affect all devices */ |
| 205 | writeb(clkreg, ftide->base + FTIDE010_CLK_MOD); |
| 206 | writeb(timreg, ftide->base + FTIDE010_MWDMA_TIMING); |
| 207 | } |
| 208 | |
| 209 | /* |
| 210 | * Store the current device (master or slave) in ap->private_data |
| 211 | * so that .qc_issue() can detect if this changes and reprogram |
| 212 | * the DMA settings. |
| 213 | */ |
| 214 | ap->private_data = adev; |
| 215 | |
| 216 | return; |
| 217 | } |
| 218 | |
| 219 | static void ftide010_set_piomode(struct ata_port *ap, struct ata_device *adev) |
| 220 | { |
| 221 | struct ftide010 *ftide = ap->host->private_data; |
| 222 | u8 pio = adev->pio_mode - XFER_PIO_0; |
| 223 | |
| 224 | dev_dbg(ftide->dev, "set PIO mode %02x, index %d\n", |
| 225 | adev->pio_mode, pio); |
| 226 | writeb(pio_active_time[pio] << 4 | pio_recovery_time[pio], |
| 227 | ftide->base + FTIDE010_PIO_TIMING); |
| 228 | } |
| 229 | |
| 230 | /* |
| 231 | * We implement our own qc_issue() callback since we may need to set up |
| 232 | * the timings differently for master and slave transfers: the CLK_MOD_REG |
| 233 | * and MWDMA_TIMING_REG is shared between master and slave, so reprogramming |
| 234 | * this may be necessary. |
| 235 | */ |
| 236 | static unsigned int ftide010_qc_issue(struct ata_queued_cmd *qc) |
| 237 | { |
| 238 | struct ata_port *ap = qc->ap; |
| 239 | struct ata_device *adev = qc->dev; |
| 240 | |
| 241 | /* |
| 242 | * If the device changed, i.e. slave->master, master->slave, |
| 243 | * then set up the DMA mode again so we are sure the timings |
| 244 | * are correct. |
| 245 | */ |
| 246 | if (adev != ap->private_data && ata_dma_enabled(adev)) |
| 247 | ftide010_set_dmamode(ap, adev); |
| 248 | |
| 249 | return ata_bmdma_qc_issue(qc); |
| 250 | } |
| 251 | |
| 252 | static struct ata_port_operations pata_ftide010_port_ops = { |
| 253 | .inherits = &ata_bmdma_port_ops, |
| 254 | .set_dmamode = ftide010_set_dmamode, |
| 255 | .set_piomode = ftide010_set_piomode, |
| 256 | .qc_issue = ftide010_qc_issue, |
| 257 | }; |
| 258 | |
| 259 | static struct ata_port_info ftide010_port_info[] = { |
| 260 | { |
| 261 | .flags = ATA_FLAG_SLAVE_POSS, |
| 262 | .mwdma_mask = ATA_MWDMA2, |
| 263 | .udma_mask = ATA_UDMA6, |
| 264 | .pio_mask = ATA_PIO4, |
| 265 | .port_ops = &pata_ftide010_port_ops, |
| 266 | }, |
| 267 | }; |
| 268 | |
| 269 | #if IS_ENABLED(CONFIG_SATA_GEMINI) |
| 270 | |
| 271 | static int pata_ftide010_gemini_port_start(struct ata_port *ap) |
| 272 | { |
| 273 | struct ftide010 *ftide = ap->host->private_data; |
| 274 | struct device *dev = ftide->dev; |
| 275 | struct sata_gemini *sg = ftide->sg; |
| 276 | int bridges = 0; |
| 277 | int ret; |
| 278 | |
| 279 | ret = ata_bmdma_port_start(ap); |
| 280 | if (ret) |
| 281 | return ret; |
| 282 | |
| 283 | if (ftide->master_to_sata0) { |
| 284 | dev_info(dev, "SATA0 (master) start\n"); |
| 285 | ret = gemini_sata_start_bridge(sg, 0); |
| 286 | if (!ret) |
| 287 | bridges++; |
| 288 | } |
| 289 | if (ftide->master_to_sata1) { |
| 290 | dev_info(dev, "SATA1 (master) start\n"); |
| 291 | ret = gemini_sata_start_bridge(sg, 1); |
| 292 | if (!ret) |
| 293 | bridges++; |
| 294 | } |
| 295 | /* Avoid double-starting */ |
| 296 | if (ftide->slave_to_sata0 && !ftide->master_to_sata0) { |
| 297 | dev_info(dev, "SATA0 (slave) start\n"); |
| 298 | ret = gemini_sata_start_bridge(sg, 0); |
| 299 | if (!ret) |
| 300 | bridges++; |
| 301 | } |
| 302 | /* Avoid double-starting */ |
| 303 | if (ftide->slave_to_sata1 && !ftide->master_to_sata1) { |
| 304 | dev_info(dev, "SATA1 (slave) start\n"); |
| 305 | ret = gemini_sata_start_bridge(sg, 1); |
| 306 | if (!ret) |
| 307 | bridges++; |
| 308 | } |
| 309 | |
| 310 | dev_info(dev, "brought %d bridges online\n", bridges); |
| 311 | return (bridges > 0) ? 0 : -EINVAL; // -ENODEV; |
| 312 | } |
| 313 | |
| 314 | static void pata_ftide010_gemini_port_stop(struct ata_port *ap) |
| 315 | { |
| 316 | struct ftide010 *ftide = ap->host->private_data; |
| 317 | struct device *dev = ftide->dev; |
| 318 | struct sata_gemini *sg = ftide->sg; |
| 319 | |
| 320 | if (ftide->master_to_sata0) { |
| 321 | dev_info(dev, "SATA0 (master) stop\n"); |
| 322 | gemini_sata_stop_bridge(sg, 0); |
| 323 | } |
| 324 | if (ftide->master_to_sata1) { |
| 325 | dev_info(dev, "SATA1 (master) stop\n"); |
| 326 | gemini_sata_stop_bridge(sg, 1); |
| 327 | } |
| 328 | /* Avoid double-stopping */ |
| 329 | if (ftide->slave_to_sata0 && !ftide->master_to_sata0) { |
| 330 | dev_info(dev, "SATA0 (slave) stop\n"); |
| 331 | gemini_sata_stop_bridge(sg, 0); |
| 332 | } |
| 333 | /* Avoid double-stopping */ |
| 334 | if (ftide->slave_to_sata1 && !ftide->master_to_sata1) { |
| 335 | dev_info(dev, "SATA1 (slave) stop\n"); |
| 336 | gemini_sata_stop_bridge(sg, 1); |
| 337 | } |
| 338 | } |
| 339 | |
| 340 | static int pata_ftide010_gemini_cable_detect(struct ata_port *ap) |
| 341 | { |
| 342 | struct ftide010 *ftide = ap->host->private_data; |
| 343 | |
| 344 | /* |
| 345 | * Return the master cable, I have no clue how to return a different |
| 346 | * cable for the slave than for the master. |
| 347 | */ |
| 348 | return ftide->master_cbl; |
| 349 | } |
| 350 | |
| 351 | static int pata_ftide010_gemini_init(struct ftide010 *ftide, |
| 352 | bool is_ata1) |
| 353 | { |
| 354 | struct device *dev = ftide->dev; |
| 355 | struct sata_gemini *sg; |
| 356 | enum gemini_muxmode muxmode; |
| 357 | |
| 358 | /* Look up SATA bridge */ |
| 359 | sg = gemini_sata_bridge_get(); |
| 360 | if (IS_ERR(sg)) |
| 361 | return PTR_ERR(sg); |
| 362 | ftide->sg = sg; |
| 363 | |
| 364 | muxmode = gemini_sata_get_muxmode(sg); |
| 365 | |
| 366 | /* Special ops */ |
| 367 | pata_ftide010_port_ops.port_start = |
| 368 | pata_ftide010_gemini_port_start; |
| 369 | pata_ftide010_port_ops.port_stop = |
| 370 | pata_ftide010_gemini_port_stop; |
| 371 | pata_ftide010_port_ops.cable_detect = |
| 372 | pata_ftide010_gemini_cable_detect; |
| 373 | |
| 374 | /* Flag port as SATA-capable */ |
| 375 | if (gemini_sata_bridge_enabled(sg, is_ata1)) |
| 376 | ftide010_port_info[0].flags |= ATA_FLAG_SATA; |
| 377 | |
| 378 | /* |
| 379 | * We assume that a simple 40-wire cable is used in the PATA mode. |
| 380 | * if you're adding a system using the PATA interface, make sure |
| 381 | * the right cable is set up here, it might be necessary to use |
| 382 | * special hardware detection or encode the cable type in the device |
| 383 | * tree with special properties. |
| 384 | */ |
| 385 | if (!is_ata1) { |
| 386 | switch (muxmode) { |
| 387 | case GEMINI_MUXMODE_0: |
| 388 | ftide->master_cbl = ATA_CBL_SATA; |
| 389 | ftide->slave_cbl = ATA_CBL_PATA40; |
| 390 | ftide->master_to_sata0 = true; |
| 391 | break; |
| 392 | case GEMINI_MUXMODE_1: |
| 393 | ftide->master_cbl = ATA_CBL_SATA; |
| 394 | ftide->slave_cbl = ATA_CBL_NONE; |
| 395 | ftide->master_to_sata0 = true; |
| 396 | break; |
| 397 | case GEMINI_MUXMODE_2: |
| 398 | ftide->master_cbl = ATA_CBL_PATA40; |
| 399 | ftide->slave_cbl = ATA_CBL_PATA40; |
| 400 | break; |
| 401 | case GEMINI_MUXMODE_3: |
| 402 | ftide->master_cbl = ATA_CBL_SATA; |
| 403 | ftide->slave_cbl = ATA_CBL_SATA; |
| 404 | ftide->master_to_sata0 = true; |
| 405 | ftide->slave_to_sata1 = true; |
| 406 | break; |
| 407 | } |
| 408 | } else { |
| 409 | switch (muxmode) { |
| 410 | case GEMINI_MUXMODE_0: |
| 411 | ftide->master_cbl = ATA_CBL_SATA; |
| 412 | ftide->slave_cbl = ATA_CBL_NONE; |
| 413 | ftide->master_to_sata1 = true; |
| 414 | break; |
| 415 | case GEMINI_MUXMODE_1: |
| 416 | ftide->master_cbl = ATA_CBL_SATA; |
| 417 | ftide->slave_cbl = ATA_CBL_PATA40; |
| 418 | ftide->master_to_sata1 = true; |
| 419 | break; |
| 420 | case GEMINI_MUXMODE_2: |
| 421 | ftide->master_cbl = ATA_CBL_SATA; |
| 422 | ftide->slave_cbl = ATA_CBL_SATA; |
| 423 | ftide->slave_to_sata0 = true; |
| 424 | ftide->master_to_sata1 = true; |
| 425 | break; |
| 426 | case GEMINI_MUXMODE_3: |
| 427 | ftide->master_cbl = ATA_CBL_PATA40; |
| 428 | ftide->slave_cbl = ATA_CBL_PATA40; |
| 429 | break; |
| 430 | } |
| 431 | } |
| 432 | dev_info(dev, "set up Gemini PATA%d\n", is_ata1); |
| 433 | |
| 434 | return 0; |
| 435 | } |
| 436 | #else |
| 437 | static int pata_ftide010_gemini_init(struct ftide010 *ftide, |
| 438 | bool is_ata1) |
| 439 | { |
| 440 | return -ENOTSUPP; |
| 441 | } |
| 442 | #endif |
| 443 | |
| 444 | |
| 445 | static int pata_ftide010_probe(struct platform_device *pdev) |
| 446 | { |
| 447 | struct device *dev = &pdev->dev; |
| 448 | struct device_node *np = dev->of_node; |
| 449 | const struct ata_port_info pi = ftide010_port_info[0]; |
| 450 | const struct ata_port_info *ppi[] = { &pi, NULL }; |
| 451 | struct ftide010 *ftide; |
| 452 | struct resource *res; |
| 453 | int irq; |
| 454 | int ret; |
| 455 | int i; |
| 456 | |
| 457 | ftide = devm_kzalloc(dev, sizeof(*ftide), GFP_KERNEL); |
| 458 | if (!ftide) |
| 459 | return -ENOMEM; |
| 460 | ftide->dev = dev; |
| 461 | |
| 462 | irq = platform_get_irq(pdev, 0); |
| 463 | if (irq < 0) |
| 464 | return irq; |
| 465 | |
| 466 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 467 | if (!res) |
| 468 | return -ENODEV; |
| 469 | |
| 470 | ftide->base = devm_ioremap_resource(dev, res); |
| 471 | if (IS_ERR(ftide->base)) |
| 472 | return PTR_ERR(ftide->base); |
| 473 | |
| 474 | ftide->pclk = devm_clk_get(dev, "PCLK"); |
| 475 | if (!IS_ERR(ftide->pclk)) { |
| 476 | ret = clk_prepare_enable(ftide->pclk); |
| 477 | if (ret) { |
| 478 | dev_err(dev, "failed to enable PCLK\n"); |
| 479 | return ret; |
| 480 | } |
| 481 | } |
| 482 | |
| 483 | /* Some special Cortina Gemini init, if needed */ |
| 484 | if (of_device_is_compatible(np, "cortina,gemini-pata")) { |
| 485 | /* |
| 486 | * We need to know which instance is probing (the |
| 487 | * Gemini has two instances of FTIDE010) and we do |
| 488 | * this simply by looking at the physical base |
| 489 | * address, which is 0x63400000 for ATA1, else we |
| 490 | * are ATA0. This will also set up the cable types. |
| 491 | */ |
| 492 | ret = pata_ftide010_gemini_init(ftide, |
| 493 | (res->start == 0x63400000)); |
| 494 | if (ret) |
| 495 | goto err_dis_clk; |
| 496 | } else { |
| 497 | /* Else assume we are connected using PATA40 */ |
| 498 | ftide->master_cbl = ATA_CBL_PATA40; |
| 499 | ftide->slave_cbl = ATA_CBL_PATA40; |
| 500 | } |
| 501 | |
| 502 | ftide->host = ata_host_alloc_pinfo(dev, ppi, 1); |
| 503 | if (!ftide->host) { |
| 504 | ret = -ENOMEM; |
| 505 | goto err_dis_clk; |
| 506 | } |
| 507 | ftide->host->private_data = ftide; |
| 508 | |
| 509 | for (i = 0; i < ftide->host->n_ports; i++) { |
| 510 | struct ata_port *ap = ftide->host->ports[i]; |
| 511 | struct ata_ioports *ioaddr = &ap->ioaddr; |
| 512 | |
| 513 | ioaddr->bmdma_addr = ftide->base + FTIDE010_DMA_REG; |
| 514 | ioaddr->cmd_addr = ftide->base + FTIDE010_CMD_DATA; |
| 515 | ioaddr->ctl_addr = ftide->base + FTIDE010_ALTSTAT_CTRL; |
| 516 | ioaddr->altstatus_addr = ftide->base + FTIDE010_ALTSTAT_CTRL; |
| 517 | ata_sff_std_ports(ioaddr); |
| 518 | } |
| 519 | |
Arnd Bergmann | d0318fb | 2017-06-22 00:00:55 +0200 | [diff] [blame] | 520 | dev_info(dev, "device ID %08x, irq %d, reg %pR\n", |
| 521 | readl(ftide->base + FTIDE010_IDE_DEVICE_ID), irq, res); |
Linus Walleij | be4e456 | 2017-06-04 10:50:08 +0200 | [diff] [blame] | 522 | |
| 523 | ret = ata_host_activate(ftide->host, irq, ata_bmdma_interrupt, |
| 524 | 0, &pata_ftide010_sht); |
| 525 | if (ret) |
| 526 | goto err_dis_clk; |
| 527 | |
| 528 | return 0; |
| 529 | |
| 530 | err_dis_clk: |
| 531 | if (!IS_ERR(ftide->pclk)) |
| 532 | clk_disable_unprepare(ftide->pclk); |
| 533 | return ret; |
| 534 | } |
| 535 | |
| 536 | static int pata_ftide010_remove(struct platform_device *pdev) |
| 537 | { |
| 538 | struct ata_host *host = platform_get_drvdata(pdev); |
| 539 | struct ftide010 *ftide = host->private_data; |
| 540 | |
| 541 | ata_host_detach(ftide->host); |
| 542 | if (!IS_ERR(ftide->pclk)) |
| 543 | clk_disable_unprepare(ftide->pclk); |
| 544 | |
| 545 | return 0; |
| 546 | } |
| 547 | |
| 548 | static const struct of_device_id pata_ftide010_of_match[] = { |
| 549 | { |
| 550 | .compatible = "faraday,ftide010", |
| 551 | }, |
| 552 | {}, |
| 553 | }; |
| 554 | |
| 555 | static struct platform_driver pata_ftide010_driver = { |
| 556 | .driver = { |
| 557 | .name = DRV_NAME, |
| 558 | .of_match_table = of_match_ptr(pata_ftide010_of_match), |
| 559 | }, |
| 560 | .probe = pata_ftide010_probe, |
| 561 | .remove = pata_ftide010_remove, |
| 562 | }; |
| 563 | module_platform_driver(pata_ftide010_driver); |
| 564 | |
| 565 | MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); |
| 566 | MODULE_LICENSE("GPL"); |
| 567 | MODULE_ALIAS("platform:" DRV_NAME); |