Blame view
drivers/ide/tx4938ide.c
5.74 KB
28502848f ide: Add tx4938id... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * TX4938 internal IDE driver * Based on tx4939ide.c. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * (C) Copyright TOSHIBA CORPORATION 2005-2007 */ #include <linux/module.h> #include <linux/types.h> #include <linux/ide.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/io.h> |
15a453a95 ide: include <asm... |
18 19 |
#include <asm/ide.h> |
28502848f ide: Add tx4938id... |
20 21 22 23 24 25 26 27 28 29 30 |
#include <asm/txx9/tx4938.h> static void tx4938ide_tune_ebusc(unsigned int ebus_ch, unsigned int gbus_clock, u8 pio) { struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); u64 cr = __raw_readq(&tx4938_ebuscptr->cr[ebus_ch]); unsigned int sp = (cr >> 4) & 3; unsigned int clock = gbus_clock / (4 - sp); unsigned int cycle = 1000000000 / clock; |
7afa05350 tx4938ide: Avoid ... |
31 32 |
unsigned int shwt; int wt; |
28502848f ide: Add tx4938id... |
33 34 35 36 |
/* Minimum DIOx- active time */ wt = DIV_ROUND_UP(t->act8b, cycle) - 2; /* IORDY setup time: 35ns */ |
7afa05350 tx4938ide: Avoid ... |
37 |
wt = max_t(int, wt, DIV_ROUND_UP(35, cycle)); |
28502848f ide: Add tx4938id... |
38 39 40 41 42 43 |
/* actual wait-cycle is max(wt & ~1, 1) */ if (wt > 2 && (wt & 1)) wt++; wt &= ~1; /* Address-valid to DIOR/DIOW setup */ shwt = DIV_ROUND_UP(t->setup, cycle); |
630a8b250 tx4938ide: Check ... |
44 45 46 47 48 49 50 51 |
/* -DIOx recovery time (SHWT * 4) and cycle time requirement */ while ((shwt * 4 + wt + (wt ? 2 : 3)) * cycle < t->cycle) shwt++; if (shwt > 7) { pr_warning("tx4938ide: SHWT violation (%d) ", shwt); shwt = 7; } |
28502848f ide: Add tx4938id... |
52 53 54 |
pr_debug("tx4938ide: ebus %d, bus cycle %dns, WT %d, SHWT %d ", ebus_ch, cycle, wt, shwt); |
630a8b250 tx4938ide: Check ... |
55 |
__raw_writeq((cr & ~0x3f007ull) | (wt << 12) | shwt, |
28502848f ide: Add tx4938id... |
56 57 |
&tx4938_ebuscptr->cr[ebus_ch]); } |
e085b3cae ide: change ->set... |
58 |
static void tx4938ide_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) |
28502848f ide: Add tx4938id... |
59 |
{ |
28502848f ide: Add tx4938id... |
60 |
struct tx4938ide_platform_info *pdata = hwif->dev->platform_data; |
e085b3cae ide: change ->set... |
61 |
u8 safe = drive->pio_mode - XFER_PIO_0; |
28502848f ide: Add tx4938id... |
62 63 64 65 |
ide_drive_t *pair; pair = ide_get_pair_dev(drive); if (pair) |
cd078af65 tx493xide: use mi... |
66 |
safe = min_t(u8, safe, pair->pio_mode - XFER_PIO_0); |
28502848f ide: Add tx4938id... |
67 68 69 70 71 72 |
tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, safe); } #ifdef __BIG_ENDIAN /* custom iops (independent from SWAP_IO_SPACE) */ |
adb1af980 ide: pass command... |
73 |
static void tx4938ide_input_data_swap(ide_drive_t *drive, struct ide_cmd *cmd, |
28502848f ide: Add tx4938id... |
74 75 76 77 78 79 80 81 |
void *buf, unsigned int len) { unsigned long port = drive->hwif->io_ports.data_addr; unsigned short *ptr = buf; unsigned int count = (len + 1) / 2; while (count--) *ptr++ = cpu_to_le16(__raw_readw((void __iomem *)port)); |
f26f6ceac tx493[89]ide: Fix... |
82 |
__ide_flush_dcache_range((unsigned long)buf, roundup(len, 2)); |
28502848f ide: Add tx4938id... |
83 |
} |
adb1af980 ide: pass command... |
84 |
static void tx4938ide_output_data_swap(ide_drive_t *drive, struct ide_cmd *cmd, |
28502848f ide: Add tx4938id... |
85 86 87 88 89 90 91 92 93 94 |
void *buf, unsigned int len) { unsigned long port = drive->hwif->io_ports.data_addr; unsigned short *ptr = buf; unsigned int count = (len + 1) / 2; while (count--) { __raw_writew(le16_to_cpu(*ptr), (void __iomem *)port); ptr++; } |
f26f6ceac tx493[89]ide: Fix... |
95 |
__ide_flush_dcache_range((unsigned long)buf, roundup(len, 2)); |
28502848f ide: Add tx4938id... |
96 97 98 99 100 101 |
} static const struct ide_tp_ops tx4938ide_tp_ops = { .exec_command = ide_exec_command, .read_status = ide_read_status, .read_altstatus = ide_read_altstatus, |
ecf3a31d2 ide: turn set_irq... |
102 |
.write_devctl = ide_write_devctl, |
28502848f ide: Add tx4938id... |
103 |
|
abb596b25 ide: turn selectp... |
104 |
.dev_select = ide_dev_select, |
d68bab503 tx493[89]ide: Rem... |
105 106 |
.tf_load = ide_tf_load, .tf_read = ide_tf_read, |
28502848f ide: Add tx4938id... |
107 108 109 110 111 112 113 114 |
.input_data = tx4938ide_input_data_swap, .output_data = tx4938ide_output_data_swap, }; #endif /* __BIG_ENDIAN */ static const struct ide_port_ops tx4938ide_port_ops = { |
3ee86dcdd tx493x: fix inden... |
115 |
.set_pio_mode = tx4938ide_set_pio_mode, |
28502848f ide: Add tx4938id... |
116 117 118 |
}; static const struct ide_port_info tx4938ide_port_info __initdata = { |
3ee86dcdd tx493x: fix inden... |
119 |
.port_ops = &tx4938ide_port_ops, |
28502848f ide: Add tx4938id... |
120 |
#ifdef __BIG_ENDIAN |
3ee86dcdd tx493x: fix inden... |
121 |
.tp_ops = &tx4938ide_tp_ops, |
28502848f ide: Add tx4938id... |
122 |
#endif |
3ee86dcdd tx493x: fix inden... |
123 124 |
.host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, .pio_mask = ATA_PIO5, |
b1d249e84 ide: remove chips... |
125 |
.chipset = ide_generic, |
28502848f ide: Add tx4938id... |
126 127 128 129 |
}; static int __init tx4938ide_probe(struct platform_device *pdev) { |
9f36d3143 ide: remove hw_re... |
130 |
struct ide_hw hw, *hws[] = { &hw }; |
28502848f ide: Add tx4938id... |
131 132 133 134 |
struct ide_host *host; struct resource *res; struct tx4938ide_platform_info *pdata = pdev->dev.platform_data; int irq, ret, i; |
9d4eb0a33 tx4938ide: Do not... |
135 |
unsigned long mapbase, mapctl; |
28502848f ide: Add tx4938id... |
136 137 138 139 140 141 142 143 144 145 |
struct ide_port_info d = tx4938ide_port_info; irq = platform_get_irq(pdev, 0); if (irq < 0) return -ENODEV; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; if (!devm_request_mem_region(&pdev->dev, res->start, |
849209054 drivers/ide/tx493... |
146 |
resource_size(res), "tx4938ide")) |
28502848f ide: Add tx4938id... |
147 148 |
return -EBUSY; mapbase = (unsigned long)devm_ioremap(&pdev->dev, res->start, |
9d4eb0a33 tx4938ide: Do not... |
149 150 151 152 153 154 |
8 << pdata->ioport_shift); mapctl = (unsigned long)devm_ioremap(&pdev->dev, res->start + 0x10000 + (6 << pdata->ioport_shift), 1 << pdata->ioport_shift); if (!mapbase || !mapctl) |
28502848f ide: Add tx4938id... |
155 156 157 158 159 |
return -EBUSY; memset(&hw, 0, sizeof(hw)); if (pdata->ioport_shift) { unsigned long port = mapbase; |
9d4eb0a33 tx4938ide: Do not... |
160 |
unsigned long ctl = mapctl; |
28502848f ide: Add tx4938id... |
161 162 163 164 |
hw.io_ports_array[0] = port; #ifdef __BIG_ENDIAN port++; |
9d4eb0a33 tx4938ide: Do not... |
165 |
ctl++; |
28502848f ide: Add tx4938id... |
166 167 168 169 |
#endif for (i = 1; i <= 7; i++) hw.io_ports_array[i] = port + (i << pdata->ioport_shift); |
9d4eb0a33 tx4938ide: Do not... |
170 |
hw.io_ports.ctl_addr = ctl; |
28502848f ide: Add tx4938id... |
171 |
} else |
9d4eb0a33 tx4938ide: Do not... |
172 |
ide_std_init_ports(&hw, mapbase, mapctl); |
28502848f ide: Add tx4938id... |
173 174 |
hw.irq = irq; hw.dev = &pdev->dev; |
9d4eb0a33 tx4938ide: Do not... |
175 176 177 |
pr_info("TX4938 IDE interface (base %#lx, ctl %#lx, irq %d) ", mapbase, mapctl, hw.irq); |
28502848f ide: Add tx4938id... |
178 179 180 181 |
if (pdata->gbus_clock) tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, 0); else d.port_ops = NULL; |
dca398305 ide: pass number ... |
182 |
ret = ide_host_add(&d, hws, 1, &host); |
9d4eb0a33 tx4938ide: Do not... |
183 184 185 |
if (!ret) platform_set_drvdata(pdev, host); return ret; |
28502848f ide: Add tx4938id... |
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
} static int __exit tx4938ide_remove(struct platform_device *pdev) { struct ide_host *host = platform_get_drvdata(pdev); ide_host_remove(host); return 0; } static struct platform_driver tx4938ide_driver = { .driver = { .name = "tx4938ide", .owner = THIS_MODULE, }, .remove = __exit_p(tx4938ide_remove), }; static int __init tx4938ide_init(void) { return platform_driver_probe(&tx4938ide_driver, tx4938ide_probe); } static void __exit tx4938ide_exit(void) { platform_driver_unregister(&tx4938ide_driver); } module_init(tx4938ide_init); module_exit(tx4938ide_exit); MODULE_DESCRIPTION("TX4938 internal IDE driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:tx4938ide"); |