Blame view

drivers/ide/tx4938ide.c 5.55 KB
28502848f   Atsushi Nemoto   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   Bartlomiej Zolnierkiewicz   ide: include <asm...
18
19
  
  #include <asm/ide.h>
28502848f   Atsushi Nemoto   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   Atsushi Nemoto   tx4938ide: Avoid ...
31
32
  	unsigned int shwt;
  	int wt;
28502848f   Atsushi Nemoto   ide: Add tx4938id...
33
34
35
36
  
  	/* Minimum DIOx- active time */
  	wt = DIV_ROUND_UP(t->act8b, cycle) - 2;
  	/* IORDY setup time: 35ns */
7afa05350   Atsushi Nemoto   tx4938ide: Avoid ...
37
  	wt = max_t(int, wt, DIV_ROUND_UP(35, cycle));
28502848f   Atsushi Nemoto   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   Atsushi Nemoto   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   Atsushi Nemoto   ide: Add tx4938id...
52
53
54
  	pr_debug("tx4938ide: ebus %d, bus cycle %dns, WT %d, SHWT %d
  ",
  		 ebus_ch, cycle, wt, shwt);
630a8b250   Atsushi Nemoto   tx4938ide: Check ...
55
  	__raw_writeq((cr & ~0x3f007ull) | (wt << 12) | shwt,
28502848f   Atsushi Nemoto   ide: Add tx4938id...
56
57
  		     &tx4938_ebuscptr->cr[ebus_ch]);
  }
e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
58
  static void tx4938ide_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
28502848f   Atsushi Nemoto   ide: Add tx4938id...
59
  {
7b6b56123   Jingoo Han   ide: use dev_get_...
60
  	struct tx4938ide_platform_info *pdata = dev_get_platdata(hwif->dev);
e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
61
  	u8 safe = drive->pio_mode - XFER_PIO_0;
28502848f   Atsushi Nemoto   ide: Add tx4938id...
62
63
64
65
  	ide_drive_t *pair;
  
  	pair = ide_get_pair_dev(drive);
  	if (pair)
cd078af65   Atsushi Nemoto   tx493xide: use mi...
66
  		safe = min_t(u8, safe, pair->pio_mode - XFER_PIO_0);
28502848f   Atsushi Nemoto   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   Bartlomiej Zolnierkiewicz   ide: pass command...
73
  static void tx4938ide_input_data_swap(ide_drive_t *drive, struct ide_cmd *cmd,
28502848f   Atsushi Nemoto   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   Atsushi Nemoto   tx493[89]ide: Fix...
82
  	__ide_flush_dcache_range((unsigned long)buf, roundup(len, 2));
28502848f   Atsushi Nemoto   ide: Add tx4938id...
83
  }
adb1af980   Bartlomiej Zolnierkiewicz   ide: pass command...
84
  static void tx4938ide_output_data_swap(ide_drive_t *drive, struct ide_cmd *cmd,
28502848f   Atsushi Nemoto   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   Atsushi Nemoto   tx493[89]ide: Fix...
95
  	__ide_flush_dcache_range((unsigned long)buf, roundup(len, 2));
28502848f   Atsushi Nemoto   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   Sergei Shtylyov   ide: turn set_irq...
102
  	.write_devctl		= ide_write_devctl,
28502848f   Atsushi Nemoto   ide: Add tx4938id...
103

abb596b25   Sergei Shtylyov   ide: turn selectp...
104
  	.dev_select		= ide_dev_select,
d68bab503   Atsushi Nemoto   tx493[89]ide: Rem...
105
106
  	.tf_load		= ide_tf_load,
  	.tf_read		= ide_tf_read,
28502848f   Atsushi Nemoto   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   Bartlomiej Zolnierkiewicz   tx493x: fix inden...
115
  	.set_pio_mode		= tx4938ide_set_pio_mode,
28502848f   Atsushi Nemoto   ide: Add tx4938id...
116
  };
e6b53703b   Andi Kleen   sections: fix sec...
117
  static const struct ide_port_info tx4938ide_port_info __initconst = {
3ee86dcdd   Bartlomiej Zolnierkiewicz   tx493x: fix inden...
118
  	.port_ops		= &tx4938ide_port_ops,
28502848f   Atsushi Nemoto   ide: Add tx4938id...
119
  #ifdef __BIG_ENDIAN
3ee86dcdd   Bartlomiej Zolnierkiewicz   tx493x: fix inden...
120
  	.tp_ops			= &tx4938ide_tp_ops,
28502848f   Atsushi Nemoto   ide: Add tx4938id...
121
  #endif
3ee86dcdd   Bartlomiej Zolnierkiewicz   tx493x: fix inden...
122
123
  	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
  	.pio_mask		= ATA_PIO5,
b1d249e84   Bartlomiej Zolnierkiewicz   ide: remove chips...
124
  	.chipset		= ide_generic,
28502848f   Atsushi Nemoto   ide: Add tx4938id...
125
126
127
128
  };
  
  static int __init tx4938ide_probe(struct platform_device *pdev)
  {
9f36d3143   Bartlomiej Zolnierkiewicz   ide: remove hw_re...
129
  	struct ide_hw hw, *hws[] = { &hw };
28502848f   Atsushi Nemoto   ide: Add tx4938id...
130
131
  	struct ide_host *host;
  	struct resource *res;
7b6b56123   Jingoo Han   ide: use dev_get_...
132
  	struct tx4938ide_platform_info *pdata = dev_get_platdata(&pdev->dev);
28502848f   Atsushi Nemoto   ide: Add tx4938id...
133
  	int irq, ret, i;
9d4eb0a33   Atsushi Nemoto   tx4938ide: Do not...
134
  	unsigned long mapbase, mapctl;
28502848f   Atsushi Nemoto   ide: Add tx4938id...
135
136
137
138
139
140
141
142
143
144
  	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   H Hartley Sweeten   drivers/ide/tx493...
145
  				     resource_size(res), "tx4938ide"))
28502848f   Atsushi Nemoto   ide: Add tx4938id...
146
147
  		return -EBUSY;
  	mapbase = (unsigned long)devm_ioremap(&pdev->dev, res->start,
9d4eb0a33   Atsushi Nemoto   tx4938ide: Do not...
148
149
150
151
152
153
  					      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   Atsushi Nemoto   ide: Add tx4938id...
154
155
156
157
158
  		return -EBUSY;
  
  	memset(&hw, 0, sizeof(hw));
  	if (pdata->ioport_shift) {
  		unsigned long port = mapbase;
9d4eb0a33   Atsushi Nemoto   tx4938ide: Do not...
159
  		unsigned long ctl = mapctl;
28502848f   Atsushi Nemoto   ide: Add tx4938id...
160
161
162
163
  
  		hw.io_ports_array[0] = port;
  #ifdef __BIG_ENDIAN
  		port++;
9d4eb0a33   Atsushi Nemoto   tx4938ide: Do not...
164
  		ctl++;
28502848f   Atsushi Nemoto   ide: Add tx4938id...
165
166
167
168
  #endif
  		for (i = 1; i <= 7; i++)
  			hw.io_ports_array[i] =
  				port + (i << pdata->ioport_shift);
9d4eb0a33   Atsushi Nemoto   tx4938ide: Do not...
169
  		hw.io_ports.ctl_addr = ctl;
28502848f   Atsushi Nemoto   ide: Add tx4938id...
170
  	} else
9d4eb0a33   Atsushi Nemoto   tx4938ide: Do not...
171
  		ide_std_init_ports(&hw, mapbase, mapctl);
28502848f   Atsushi Nemoto   ide: Add tx4938id...
172
173
  	hw.irq = irq;
  	hw.dev = &pdev->dev;
9d4eb0a33   Atsushi Nemoto   tx4938ide: Do not...
174
175
176
  	pr_info("TX4938 IDE interface (base %#lx, ctl %#lx, irq %d)
  ",
  		mapbase, mapctl, hw.irq);
28502848f   Atsushi Nemoto   ide: Add tx4938id...
177
178
179
180
  	if (pdata->gbus_clock)
  		tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, 0);
  	else
  		d.port_ops = NULL;
dca398305   Bartlomiej Zolnierkiewicz   ide: pass number ...
181
  	ret = ide_host_add(&d, hws, 1, &host);
9d4eb0a33   Atsushi Nemoto   tx4938ide: Do not...
182
183
184
  	if (!ret)
  		platform_set_drvdata(pdev, host);
  	return ret;
28502848f   Atsushi Nemoto   ide: Add tx4938id...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
  }
  
  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),
  };
5abf6c643   Jingoo Han   ide: tx4938ide: u...
202
  module_platform_driver_probe(tx4938ide_driver, tx4938ide_probe);
28502848f   Atsushi Nemoto   ide: Add tx4938id...
203
204
205
206
  
  MODULE_DESCRIPTION("TX4938 internal IDE driver");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("platform:tx4938ide");