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