Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ata: pata_of_platform: Allow to use 16-bit wide data transfer

In some cases, the system bus can be configured for 16-bit mode,
in this case using read/write functions for 32-bit values
results in two cycles of 16 bits each, which is wrong.
This patch adds the devicetree flag to switch the driver to
use 16-bit mode for I/O transfers.

Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Alexander Shiyan and committed by
Jens Axboe
f3d5e4f1 740c68a0

+19 -12
+5 -1
drivers/ata/pata_of_platform.c
··· 32 32 unsigned int reg_shift = 0; 33 33 int pio_mode = 0; 34 34 int pio_mask; 35 + bool use16bit; 35 36 36 37 ret = of_address_to_resource(dn, 0, &io_res); 37 38 if (ret) { ··· 61 60 dev_info(&ofdev->dev, "pio-mode unspecified, assuming PIO0\n"); 62 61 } 63 62 63 + use16bit = of_property_read_bool(dn, "ata-generic,use16bit"); 64 + 64 65 pio_mask = 1 << pio_mode; 65 66 pio_mask |= (1 << pio_mode) - 1; 66 67 67 68 return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, irq_res, 68 - reg_shift, pio_mask, &pata_platform_sht); 69 + reg_shift, pio_mask, &pata_platform_sht, 70 + use16bit); 69 71 } 70 72 71 73 static const struct of_device_id pata_of_platform_match[] = {
+12 -10
drivers/ata/pata_platform.c
··· 47 47 ATA_PIO_SHT(DRV_NAME), 48 48 }; 49 49 50 - static struct ata_port_operations pata_platform_port_ops = { 51 - .inherits = &ata_sff_port_ops, 52 - .sff_data_xfer = ata_sff_data_xfer32, 53 - .cable_detect = ata_cable_unknown, 54 - .set_mode = pata_platform_set_mode, 55 - }; 56 - 57 50 static void pata_platform_setup_port(struct ata_ioports *ioaddr, 58 51 unsigned int shift) 59 52 { ··· 72 79 * @ioport_shift: I/O port shift 73 80 * @__pio_mask: PIO mask 74 81 * @sht: scsi_host_template to use when registering 82 + * @use16bit: Flag to indicate 16-bit IO instead of 32-bit 75 83 * 76 84 * Register a platform bus IDE interface. Such interfaces are PIO and we 77 85 * assume do not support IRQ sharing. ··· 95 101 int __pata_platform_probe(struct device *dev, struct resource *io_res, 96 102 struct resource *ctl_res, struct resource *irq_res, 97 103 unsigned int ioport_shift, int __pio_mask, 98 - struct scsi_host_template *sht) 104 + struct scsi_host_template *sht, bool use16bit) 99 105 { 100 106 struct ata_host *host; 101 107 struct ata_port *ap; ··· 125 131 return -ENOMEM; 126 132 ap = host->ports[0]; 127 133 128 - ap->ops = &pata_platform_port_ops; 134 + ap->ops = devm_kzalloc(dev, sizeof(*ap->ops), GFP_KERNEL); 135 + ap->ops->inherits = &ata_sff_port_ops; 136 + ap->ops->cable_detect = ata_cable_unknown; 137 + ap->ops->set_mode = pata_platform_set_mode; 138 + if (use16bit) 139 + ap->ops->sff_data_xfer = ata_sff_data_xfer; 140 + else 141 + ap->ops->sff_data_xfer = ata_sff_data_xfer32; 142 + 129 143 ap->pio_mask = __pio_mask; 130 144 ap->flags |= ATA_FLAG_SLAVE_POSS; 131 145 ··· 220 218 221 219 return __pata_platform_probe(&pdev->dev, io_res, ctl_res, irq_res, 222 220 pp_info ? pp_info->ioport_shift : 0, 223 - pio_mask, &pata_platform_sht); 221 + pio_mask, &pata_platform_sht, false); 224 222 } 225 223 226 224 static struct platform_driver pata_platform_driver = {
+2 -1
include/linux/ata_platform.h
··· 19 19 struct resource *irq_res, 20 20 unsigned int ioport_shift, 21 21 int __pio_mask, 22 - struct scsi_host_template *sht); 22 + struct scsi_host_template *sht, 23 + bool use16bit); 23 24 24 25 /* 25 26 * Marvell SATA private data