Blame view

drivers/ata/sata_rcar.c 26.7 KB
bb39ba6a8   Kuninori Morimoto   sata_rcar: conver...
1
  // SPDX-License-Identifier: GPL-2.0+
163cf81d2   Vladimir Barinov   libata: add R-Car...
2
3
4
5
  /*
   * Renesas R-Car SATA driver
   *
   * Author: Vladimir Barinov <source@cogentembedded.com>
5bc27ef72   Mikhail Ulyanov   sata_rcar: extend...
6
7
   * Copyright (C) 2013-2015 Cogent Embedded, Inc.
   * Copyright (C) 2013-2015 Renesas Solutions Corp.
163cf81d2   Vladimir Barinov   libata: add R-Car...
8
9
10
11
12
13
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/ata.h>
  #include <linux/libata.h>
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
14
  #include <linux/of_device.h>
163cf81d2   Vladimir Barinov   libata: add R-Car...
15
  #include <linux/platform_device.h>
1ecd34ddf   Geert Uytterhoeven   ata: sata_rcar: A...
16
  #include <linux/pm_runtime.h>
2de1d5e15   Sachin Kamat   sata_rcar: Conver...
17
  #include <linux/err.h>
163cf81d2   Vladimir Barinov   libata: add R-Car...
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  
  #define DRV_NAME "sata_rcar"
  
  /* SH-Navi2G/ATAPI-ATA compatible task registers */
  #define DATA_REG			0x100
  #define SDEVCON_REG			0x138
  
  /* SH-Navi2G/ATAPI module compatible control registers */
  #define ATAPI_CONTROL1_REG		0x180
  #define ATAPI_STATUS_REG		0x184
  #define ATAPI_INT_ENABLE_REG		0x188
  #define ATAPI_DTB_ADR_REG		0x198
  #define ATAPI_DMA_START_ADR_REG		0x19C
  #define ATAPI_DMA_TRANS_CNT_REG		0x1A0
  #define ATAPI_CONTROL2_REG		0x1A4
  #define ATAPI_SIG_ST_REG		0x1B0
  #define ATAPI_BYTE_SWAP_REG		0x1BC
  
  /* ATAPI control 1 register (ATAPI_CONTROL1) bits */
  #define ATAPI_CONTROL1_ISM		BIT(16)
  #define ATAPI_CONTROL1_DTA32M		BIT(11)
  #define ATAPI_CONTROL1_RESET		BIT(7)
  #define ATAPI_CONTROL1_DESE		BIT(3)
  #define ATAPI_CONTROL1_RW		BIT(2)
  #define ATAPI_CONTROL1_STOP		BIT(1)
  #define ATAPI_CONTROL1_START		BIT(0)
  
  /* ATAPI status register (ATAPI_STATUS) bits */
  #define ATAPI_STATUS_SATAINT		BIT(11)
  #define ATAPI_STATUS_DNEND		BIT(6)
  #define ATAPI_STATUS_DEVTRM		BIT(5)
  #define ATAPI_STATUS_DEVINT		BIT(4)
  #define ATAPI_STATUS_ERR		BIT(2)
  #define ATAPI_STATUS_NEND		BIT(1)
  #define ATAPI_STATUS_ACT		BIT(0)
  
  /* Interrupt enable register (ATAPI_INT_ENABLE) bits */
  #define ATAPI_INT_ENABLE_SATAINT	BIT(11)
  #define ATAPI_INT_ENABLE_DNEND		BIT(6)
  #define ATAPI_INT_ENABLE_DEVTRM		BIT(5)
  #define ATAPI_INT_ENABLE_DEVINT		BIT(4)
  #define ATAPI_INT_ENABLE_ERR		BIT(2)
  #define ATAPI_INT_ENABLE_NEND		BIT(1)
  #define ATAPI_INT_ENABLE_ACT		BIT(0)
  
  /* Access control registers for physical layer control register */
  #define SATAPHYADDR_REG			0x200
  #define SATAPHYWDATA_REG		0x204
  #define SATAPHYACCEN_REG		0x208
  #define SATAPHYRESET_REG		0x20C
  #define SATAPHYRDATA_REG		0x210
  #define SATAPHYACK_REG			0x214
  
  /* Physical layer control address command register (SATAPHYADDR) bits */
  #define SATAPHYADDR_PHYRATEMODE		BIT(10)
  #define SATAPHYADDR_PHYCMD_READ		BIT(9)
  #define SATAPHYADDR_PHYCMD_WRITE	BIT(8)
  
  /* Physical layer control enable register (SATAPHYACCEN) bits */
  #define SATAPHYACCEN_PHYLANE		BIT(0)
  
  /* Physical layer control reset register (SATAPHYRESET) bits */
  #define SATAPHYRESET_PHYRST		BIT(1)
  #define SATAPHYRESET_PHYSRES		BIT(0)
  
  /* Physical layer control acknowledge register (SATAPHYACK) bits */
  #define SATAPHYACK_PHYACK		BIT(0)
  
  /* Serial-ATA HOST control registers */
  #define BISTCONF_REG			0x102C
  #define SDATA_REG			0x1100
  #define SSDEVCON_REG			0x1204
  
  #define SCRSSTS_REG			0x1400
  #define SCRSERR_REG			0x1404
  #define SCRSCON_REG			0x1408
  #define SCRSACT_REG			0x140C
  
  #define SATAINTSTAT_REG			0x1508
  #define SATAINTMASK_REG			0x150C
  
  /* SATA INT status register (SATAINTSTAT) bits */
  #define SATAINTSTAT_SERR		BIT(3)
  #define SATAINTSTAT_ATA			BIT(0)
  
  /* SATA INT mask register (SATAINTSTAT) bits */
  #define SATAINTMASK_SERRMSK		BIT(3)
  #define SATAINTMASK_ERRMSK		BIT(2)
  #define SATAINTMASK_ERRCRTMSK		BIT(1)
  #define SATAINTMASK_ATAMSK		BIT(0)
e207610ff   Wolfram Sang   ata: sata_rcar: r...
108
109
  #define SATAINTMASK_ALL_GEN1		0x7ff
  #define SATAINTMASK_ALL_GEN2		0xfff
163cf81d2   Vladimir Barinov   libata: add R-Car...
110
111
112
113
114
115
116
117
118
119
120
121
  
  #define SATA_RCAR_INT_MASK		(SATAINTMASK_SERRMSK | \
  					 SATAINTMASK_ATAMSK)
  
  /* Physical Layer Control Registers */
  #define SATAPCTLR1_REG			0x43
  #define SATAPCTLR2_REG			0x52
  #define SATAPCTLR3_REG			0x5A
  #define SATAPCTLR4_REG			0x60
  
  /* Descriptor table word 0 bit (when DTA32M = 1) */
  #define SATA_RCAR_DTEND			BIT(0)
8bfbeed58   Sergei Shtylyov   sata_rcar: correc...
122
  #define SATA_RCAR_DMA_BOUNDARY		0x1FFFFFFEUL
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  /* Gen2 Physical Layer Control Registers */
  #define RCAR_GEN2_PHY_CTL1_REG		0x1704
  #define RCAR_GEN2_PHY_CTL1		0x34180002
  #define RCAR_GEN2_PHY_CTL1_SS		0xC180	/* Spread Spectrum */
  
  #define RCAR_GEN2_PHY_CTL2_REG		0x170C
  #define RCAR_GEN2_PHY_CTL2		0x00002303
  
  #define RCAR_GEN2_PHY_CTL3_REG		0x171C
  #define RCAR_GEN2_PHY_CTL3		0x000B0194
  
  #define RCAR_GEN2_PHY_CTL4_REG		0x1724
  #define RCAR_GEN2_PHY_CTL4		0x00030994
  
  #define RCAR_GEN2_PHY_CTL5_REG		0x1740
  #define RCAR_GEN2_PHY_CTL5		0x03004001
  #define RCAR_GEN2_PHY_CTL5_DC		BIT(1)	/* DC connection */
  #define RCAR_GEN2_PHY_CTL5_TR		BIT(2)	/* Termination Resistor */
  
  enum sata_rcar_type {
  	RCAR_GEN1_SATA,
  	RCAR_GEN2_SATA,
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
145
  	RCAR_GEN3_SATA,
aa1cf2588   Simon Horman   ata: sata_rcar: D...
146
  	RCAR_R8A7790_ES1_SATA,
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
147
  };
163cf81d2   Vladimir Barinov   libata: add R-Car...
148
149
  struct sata_rcar_priv {
  	void __iomem *base;
e207610ff   Wolfram Sang   ata: sata_rcar: r...
150
  	u32 sataint_mask;
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
151
  	enum sata_rcar_type type;
163cf81d2   Vladimir Barinov   libata: add R-Car...
152
  };
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
153
  static void sata_rcar_gen1_phy_preinit(struct sata_rcar_priv *priv)
163cf81d2   Vladimir Barinov   libata: add R-Car...
154
  {
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
155
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
156
  	/* idle state */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
157
  	iowrite32(0, base + SATAPHYADDR_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
158
  	/* reset */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
159
  	iowrite32(SATAPHYRESET_PHYRST, base + SATAPHYRESET_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
160
161
  	udelay(10);
  	/* deassert reset */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
162
  	iowrite32(0, base + SATAPHYRESET_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
163
  }
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
164
165
  static void sata_rcar_gen1_phy_write(struct sata_rcar_priv *priv, u16 reg,
  				     u32 val, int group)
163cf81d2   Vladimir Barinov   libata: add R-Car...
166
  {
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
167
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
168
169
170
  	int timeout;
  
  	/* deassert reset */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
171
  	iowrite32(0, base + SATAPHYRESET_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
172
  	/* lane 1 */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
173
  	iowrite32(SATAPHYACCEN_PHYLANE, base + SATAPHYACCEN_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
174
  	/* write phy register value */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
175
  	iowrite32(val, base + SATAPHYWDATA_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
176
177
178
179
  	/* set register group */
  	if (group)
  		reg |= SATAPHYADDR_PHYRATEMODE;
  	/* write command */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
180
  	iowrite32(SATAPHYADDR_PHYCMD_WRITE | reg, base + SATAPHYADDR_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
181
182
  	/* wait for ack */
  	for (timeout = 0; timeout < 100; timeout++) {
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
183
  		val = ioread32(base + SATAPHYACK_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
184
185
186
187
188
189
190
  		if (val & SATAPHYACK_PHYACK)
  			break;
  	}
  	if (timeout >= 100)
  		pr_err("%s timeout
  ", __func__);
  	/* idle state */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
191
  	iowrite32(0, base + SATAPHYADDR_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
192
  }
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  static void sata_rcar_gen1_phy_init(struct sata_rcar_priv *priv)
  {
  	sata_rcar_gen1_phy_preinit(priv);
  	sata_rcar_gen1_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 0);
  	sata_rcar_gen1_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 1);
  	sata_rcar_gen1_phy_write(priv, SATAPCTLR3_REG, 0x0000A061, 0);
  	sata_rcar_gen1_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 0);
  	sata_rcar_gen1_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 1);
  	sata_rcar_gen1_phy_write(priv, SATAPCTLR4_REG, 0x28E80000, 0);
  }
  
  static void sata_rcar_gen2_phy_init(struct sata_rcar_priv *priv)
  {
  	void __iomem *base = priv->base;
  
  	iowrite32(RCAR_GEN2_PHY_CTL1, base + RCAR_GEN2_PHY_CTL1_REG);
  	iowrite32(RCAR_GEN2_PHY_CTL2, base + RCAR_GEN2_PHY_CTL2_REG);
  	iowrite32(RCAR_GEN2_PHY_CTL3, base + RCAR_GEN2_PHY_CTL3_REG);
  	iowrite32(RCAR_GEN2_PHY_CTL4, base + RCAR_GEN2_PHY_CTL4_REG);
  	iowrite32(RCAR_GEN2_PHY_CTL5 | RCAR_GEN2_PHY_CTL5_DC |
  		  RCAR_GEN2_PHY_CTL5_TR, base + RCAR_GEN2_PHY_CTL5_REG);
  }
163cf81d2   Vladimir Barinov   libata: add R-Car...
215
216
217
218
219
  static void sata_rcar_freeze(struct ata_port *ap)
  {
  	struct sata_rcar_priv *priv = ap->host->private_data;
  
  	/* mask */
e207610ff   Wolfram Sang   ata: sata_rcar: r...
220
  	iowrite32(priv->sataint_mask, priv->base + SATAINTMASK_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
221
222
223
224
225
226
227
  
  	ata_sff_freeze(ap);
  }
  
  static void sata_rcar_thaw(struct ata_port *ap)
  {
  	struct sata_rcar_priv *priv = ap->host->private_data;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
228
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
229
230
  
  	/* ack */
5a0a6a4f1   Tejun Heo   Merge branch 'lib...
231
  	iowrite32(~(u32)SATA_RCAR_INT_MASK, base + SATAINTSTAT_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
232
233
234
235
  
  	ata_sff_thaw(ap);
  
  	/* unmask */
e207610ff   Wolfram Sang   ata: sata_rcar: r...
236
  	iowrite32(priv->sataint_mask & ~SATA_RCAR_INT_MASK, base + SATAINTMASK_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
  }
  
  static void sata_rcar_ioread16_rep(void __iomem *reg, void *buffer, int count)
  {
  	u16 *ptr = buffer;
  
  	while (count--) {
  		u16 data = ioread32(reg);
  
  		*ptr++ = data;
  	}
  }
  
  static void sata_rcar_iowrite16_rep(void __iomem *reg, void *buffer, int count)
  {
  	const u16 *ptr = buffer;
  
  	while (count--)
  		iowrite32(*ptr++, reg);
  }
  
  static u8 sata_rcar_check_status(struct ata_port *ap)
  {
  	return ioread32(ap->ioaddr.status_addr);
  }
  
  static u8 sata_rcar_check_altstatus(struct ata_port *ap)
  {
  	return ioread32(ap->ioaddr.altstatus_addr);
  }
  
  static void sata_rcar_set_devctl(struct ata_port *ap, u8 ctl)
  {
  	iowrite32(ctl, ap->ioaddr.ctl_addr);
  }
  
  static void sata_rcar_dev_select(struct ata_port *ap, unsigned int device)
  {
  	iowrite32(ATA_DEVICE_OBS, ap->ioaddr.device_addr);
  	ata_sff_pause(ap);	/* needed; also flushes, for mmio */
  }
  
  static unsigned int sata_rcar_ata_devchk(struct ata_port *ap,
  					 unsigned int device)
  {
  	struct ata_ioports *ioaddr = &ap->ioaddr;
  	u8 nsect, lbal;
  
  	sata_rcar_dev_select(ap, device);
  
  	iowrite32(0x55, ioaddr->nsect_addr);
  	iowrite32(0xaa, ioaddr->lbal_addr);
  
  	iowrite32(0xaa, ioaddr->nsect_addr);
  	iowrite32(0x55, ioaddr->lbal_addr);
  
  	iowrite32(0x55, ioaddr->nsect_addr);
  	iowrite32(0xaa, ioaddr->lbal_addr);
  
  	nsect = ioread32(ioaddr->nsect_addr);
  	lbal  = ioread32(ioaddr->lbal_addr);
  
  	if (nsect == 0x55 && lbal == 0xaa)
  		return 1;	/* found a device */
  
  	return 0;		/* nothing found */
  }
  
  static int sata_rcar_wait_after_reset(struct ata_link *link,
  				      unsigned long deadline)
  {
  	struct ata_port *ap = link->ap;
  
  	ata_msleep(ap, ATA_WAIT_AFTER_RESET);
  
  	return ata_sff_wait_ready(link, deadline);
  }
  
  static int sata_rcar_bus_softreset(struct ata_port *ap, unsigned long deadline)
  {
  	struct ata_ioports *ioaddr = &ap->ioaddr;
  
  	DPRINTK("ata%u: bus reset via SRST
  ", ap->print_id);
  
  	/* software reset.  causes dev0 to be selected */
  	iowrite32(ap->ctl, ioaddr->ctl_addr);
  	udelay(20);
  	iowrite32(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
  	udelay(20);
  	iowrite32(ap->ctl, ioaddr->ctl_addr);
  	ap->last_ctl = ap->ctl;
  
  	/* wait the port to become ready */
  	return sata_rcar_wait_after_reset(&ap->link, deadline);
  }
  
  static int sata_rcar_softreset(struct ata_link *link, unsigned int *classes,
  			       unsigned long deadline)
  {
  	struct ata_port *ap = link->ap;
  	unsigned int devmask = 0;
  	int rc;
  	u8 err;
  
  	/* determine if device 0 is present */
  	if (sata_rcar_ata_devchk(ap, 0))
  		devmask |= 1 << 0;
  
  	/* issue bus reset */
  	DPRINTK("about to softreset, devmask=%x
  ", devmask);
  	rc = sata_rcar_bus_softreset(ap, deadline);
  	/* if link is occupied, -ENODEV too is an error */
  	if (rc && (rc != -ENODEV || sata_scr_valid(link))) {
  		ata_link_err(link, "SRST failed (errno=%d)
  ", rc);
  		return rc;
  	}
  
  	/* determine by signature whether we have ATA or ATAPI devices */
  	classes[0] = ata_sff_dev_classify(&link->device[0], devmask, &err);
  
  	DPRINTK("classes[0]=%u
  ", classes[0]);
  	return 0;
  }
  
  static void sata_rcar_tf_load(struct ata_port *ap,
  			      const struct ata_taskfile *tf)
  {
  	struct ata_ioports *ioaddr = &ap->ioaddr;
  	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
  
  	if (tf->ctl != ap->last_ctl) {
  		iowrite32(tf->ctl, ioaddr->ctl_addr);
  		ap->last_ctl = tf->ctl;
  		ata_wait_idle(ap);
  	}
  
  	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
  		iowrite32(tf->hob_feature, ioaddr->feature_addr);
  		iowrite32(tf->hob_nsect, ioaddr->nsect_addr);
  		iowrite32(tf->hob_lbal, ioaddr->lbal_addr);
  		iowrite32(tf->hob_lbam, ioaddr->lbam_addr);
  		iowrite32(tf->hob_lbah, ioaddr->lbah_addr);
  		VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X
  ",
  			tf->hob_feature,
  			tf->hob_nsect,
  			tf->hob_lbal,
  			tf->hob_lbam,
  			tf->hob_lbah);
  	}
  
  	if (is_addr) {
  		iowrite32(tf->feature, ioaddr->feature_addr);
  		iowrite32(tf->nsect, ioaddr->nsect_addr);
  		iowrite32(tf->lbal, ioaddr->lbal_addr);
  		iowrite32(tf->lbam, ioaddr->lbam_addr);
  		iowrite32(tf->lbah, ioaddr->lbah_addr);
  		VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X
  ",
  			tf->feature,
  			tf->nsect,
  			tf->lbal,
  			tf->lbam,
  			tf->lbah);
  	}
  
  	if (tf->flags & ATA_TFLAG_DEVICE) {
  		iowrite32(tf->device, ioaddr->device_addr);
  		VPRINTK("device 0x%X
  ", tf->device);
  	}
  
  	ata_wait_idle(ap);
  }
  
  static void sata_rcar_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
  {
  	struct ata_ioports *ioaddr = &ap->ioaddr;
  
  	tf->command = sata_rcar_check_status(ap);
  	tf->feature = ioread32(ioaddr->error_addr);
  	tf->nsect = ioread32(ioaddr->nsect_addr);
  	tf->lbal = ioread32(ioaddr->lbal_addr);
  	tf->lbam = ioread32(ioaddr->lbam_addr);
  	tf->lbah = ioread32(ioaddr->lbah_addr);
  	tf->device = ioread32(ioaddr->device_addr);
  
  	if (tf->flags & ATA_TFLAG_LBA48) {
  		iowrite32(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
  		tf->hob_feature = ioread32(ioaddr->error_addr);
  		tf->hob_nsect = ioread32(ioaddr->nsect_addr);
  		tf->hob_lbal = ioread32(ioaddr->lbal_addr);
  		tf->hob_lbam = ioread32(ioaddr->lbam_addr);
  		tf->hob_lbah = ioread32(ioaddr->lbah_addr);
  		iowrite32(tf->ctl, ioaddr->ctl_addr);
  		ap->last_ctl = tf->ctl;
  	}
  }
  
  static void sata_rcar_exec_command(struct ata_port *ap,
  				   const struct ata_taskfile *tf)
  {
  	DPRINTK("ata%u: cmd 0x%X
  ", ap->print_id, tf->command);
  
  	iowrite32(tf->command, ap->ioaddr.command_addr);
  	ata_sff_pause(ap);
  }
989e0aac1   Bartlomiej Zolnierkiewicz   ata: pass queued ...
449
  static unsigned int sata_rcar_data_xfer(struct ata_queued_cmd *qc,
163cf81d2   Vladimir Barinov   libata: add R-Car...
450
451
452
  					      unsigned char *buf,
  					      unsigned int buflen, int rw)
  {
989e0aac1   Bartlomiej Zolnierkiewicz   ata: pass queued ...
453
  	struct ata_port *ap = qc->dev->link->ap;
163cf81d2   Vladimir Barinov   libata: add R-Car...
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
  	void __iomem *data_addr = ap->ioaddr.data_addr;
  	unsigned int words = buflen >> 1;
  
  	/* Transfer multiple of 2 bytes */
  	if (rw == READ)
  		sata_rcar_ioread16_rep(data_addr, buf, words);
  	else
  		sata_rcar_iowrite16_rep(data_addr, buf, words);
  
  	/* Transfer trailing byte, if any. */
  	if (unlikely(buflen & 0x01)) {
  		unsigned char pad[2] = { };
  
  		/* Point buf to the tail of buffer */
  		buf += buflen - 1;
  
  		/*
  		 * Use io*16_rep() accessors here as well to avoid pointlessly
  		 * swapping bytes to and from on the big endian machines...
  		 */
  		if (rw == READ) {
  			sata_rcar_ioread16_rep(data_addr, pad, 1);
  			*buf = pad[0];
  		} else {
  			pad[0] = *buf;
  			sata_rcar_iowrite16_rep(data_addr, pad, 1);
  		}
  		words++;
  	}
  
  	return words << 1;
  }
  
  static void sata_rcar_drain_fifo(struct ata_queued_cmd *qc)
  {
  	int count;
  	struct ata_port *ap;
  
  	/* We only need to flush incoming data when a command was running */
  	if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE)
  		return;
  
  	ap = qc->ap;
  	/* Drain up to 64K of data before we give up this recovery method */
  	for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ) &&
  			count < 65536; count += 2)
  		ioread32(ap->ioaddr.data_addr);
  
  	/* Can become DEBUG later */
  	if (count)
  		ata_port_dbg(ap, "drained %d bytes to clear DRQ
  ", count);
  }
  
  static int sata_rcar_scr_read(struct ata_link *link, unsigned int sc_reg,
  			      u32 *val)
  {
  	if (sc_reg > SCR_ACTIVE)
  		return -EINVAL;
  
  	*val = ioread32(link->ap->ioaddr.scr_addr + (sc_reg << 2));
  	return 0;
  }
  
  static int sata_rcar_scr_write(struct ata_link *link, unsigned int sc_reg,
  			       u32 val)
  {
  	if (sc_reg > SCR_ACTIVE)
  		return -EINVAL;
  
  	iowrite32(val, link->ap->ioaddr.scr_addr + (sc_reg << 2));
  	return 0;
  }
  
  static void sata_rcar_bmdma_fill_sg(struct ata_queued_cmd *qc)
  {
  	struct ata_port *ap = qc->ap;
  	struct ata_bmdma_prd *prd = ap->bmdma_prd;
  	struct scatterlist *sg;
333279c82   Sergei Shtylyov   sata_rcar: kill s...
533
  	unsigned int si;
163cf81d2   Vladimir Barinov   libata: add R-Car...
534

163cf81d2   Vladimir Barinov   libata: add R-Car...
535
  	for_each_sg(qc->sg, sg, qc->n_elem, si) {
333279c82   Sergei Shtylyov   sata_rcar: kill s...
536
  		u32 addr, sg_len;
163cf81d2   Vladimir Barinov   libata: add R-Car...
537
538
539
540
541
542
543
  
  		/*
  		 * Note: h/w doesn't support 64-bit, so we unconditionally
  		 * truncate dma_addr_t to u32.
  		 */
  		addr = (u32)sg_dma_address(sg);
  		sg_len = sg_dma_len(sg);
333279c82   Sergei Shtylyov   sata_rcar: kill s...
544
545
546
547
  		prd[si].addr = cpu_to_le32(addr);
  		prd[si].flags_len = cpu_to_le32(sg_len);
  		VPRINTK("PRD[%u] = (0x%X, 0x%X)
  ", si, addr, sg_len);
163cf81d2   Vladimir Barinov   libata: add R-Car...
548
549
550
  	}
  
  	/* end-of-table flag */
333279c82   Sergei Shtylyov   sata_rcar: kill s...
551
  	prd[si - 1].addr |= cpu_to_le32(SATA_RCAR_DTEND);
163cf81d2   Vladimir Barinov   libata: add R-Car...
552
  }
95364f367   Jiri Slaby   ata: make qc_prep...
553
  static enum ata_completion_errors sata_rcar_qc_prep(struct ata_queued_cmd *qc)
163cf81d2   Vladimir Barinov   libata: add R-Car...
554
555
  {
  	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
95364f367   Jiri Slaby   ata: make qc_prep...
556
  		return AC_ERR_OK;
163cf81d2   Vladimir Barinov   libata: add R-Car...
557
558
  
  	sata_rcar_bmdma_fill_sg(qc);
95364f367   Jiri Slaby   ata: make qc_prep...
559
560
  
  	return AC_ERR_OK;
163cf81d2   Vladimir Barinov   libata: add R-Car...
561
562
563
564
565
566
  }
  
  static void sata_rcar_bmdma_setup(struct ata_queued_cmd *qc)
  {
  	struct ata_port *ap = qc->ap;
  	unsigned int rw = qc->tf.flags & ATA_TFLAG_WRITE;
163cf81d2   Vladimir Barinov   libata: add R-Car...
567
  	struct sata_rcar_priv *priv = ap->host->private_data;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
568
569
  	void __iomem *base = priv->base;
  	u32 dmactl;
163cf81d2   Vladimir Barinov   libata: add R-Car...
570
571
572
  
  	/* load PRD table addr. */
  	mb();   /* make sure PRD table writes are visible to controller */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
573
  	iowrite32(ap->bmdma_prd_dma, base + ATAPI_DTB_ADR_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
574
575
  
  	/* specify data direction, triple-check start bit is clear */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
576
  	dmactl = ioread32(base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
577
578
579
580
581
582
583
  	dmactl &= ~(ATAPI_CONTROL1_RW | ATAPI_CONTROL1_STOP);
  	if (dmactl & ATAPI_CONTROL1_START) {
  		dmactl &= ~ATAPI_CONTROL1_START;
  		dmactl |= ATAPI_CONTROL1_STOP;
  	}
  	if (!rw)
  		dmactl |= ATAPI_CONTROL1_RW;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
584
  	iowrite32(dmactl, base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
585
586
587
588
589
590
591
592
  
  	/* issue r/w command */
  	ap->ops->sff_exec_command(ap, &qc->tf);
  }
  
  static void sata_rcar_bmdma_start(struct ata_queued_cmd *qc)
  {
  	struct ata_port *ap = qc->ap;
163cf81d2   Vladimir Barinov   libata: add R-Car...
593
  	struct sata_rcar_priv *priv = ap->host->private_data;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
594
595
  	void __iomem *base = priv->base;
  	u32 dmactl;
163cf81d2   Vladimir Barinov   libata: add R-Car...
596
597
  
  	/* start host DMA transaction */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
598
  	dmactl = ioread32(base + ATAPI_CONTROL1_REG);
df7e131f6   Sergei Shtylyov   sata_rcar: clear ...
599
  	dmactl &= ~ATAPI_CONTROL1_STOP;
163cf81d2   Vladimir Barinov   libata: add R-Car...
600
  	dmactl |= ATAPI_CONTROL1_START;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
601
  	iowrite32(dmactl, base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
602
603
604
605
606
607
  }
  
  static void sata_rcar_bmdma_stop(struct ata_queued_cmd *qc)
  {
  	struct ata_port *ap = qc->ap;
  	struct sata_rcar_priv *priv = ap->host->private_data;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
608
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
609
610
611
  	u32 dmactl;
  
  	/* force termination of DMA transfer if active */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
612
  	dmactl = ioread32(base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
613
614
615
  	if (dmactl & ATAPI_CONTROL1_START) {
  		dmactl &= ~ATAPI_CONTROL1_START;
  		dmactl |= ATAPI_CONTROL1_STOP;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
616
  		iowrite32(dmactl, base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
617
618
619
620
621
622
623
624
625
  	}
  
  	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
  	ata_sff_dma_pause(ap);
  }
  
  static u8 sata_rcar_bmdma_status(struct ata_port *ap)
  {
  	struct sata_rcar_priv *priv = ap->host->private_data;
163cf81d2   Vladimir Barinov   libata: add R-Car...
626
  	u8 host_stat = 0;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
627
  	u32 status;
163cf81d2   Vladimir Barinov   libata: add R-Car...
628
629
630
631
632
633
634
635
636
637
638
  
  	status = ioread32(priv->base + ATAPI_STATUS_REG);
  	if (status & ATAPI_STATUS_DEVINT)
  		host_stat |= ATA_DMA_INTR;
  	if (status & ATAPI_STATUS_ACT)
  		host_stat |= ATA_DMA_ACTIVE;
  
  	return host_stat;
  }
  
  static struct scsi_host_template sata_rcar_sht = {
8bfbeed58   Sergei Shtylyov   sata_rcar: correc...
639
640
641
642
643
644
645
646
  	ATA_BASE_SHT(DRV_NAME),
  	/*
  	 * This controller allows transfer chunks up to 512MB which cross 64KB
  	 * boundaries, therefore the DMA limits are more relaxed than standard
  	 * ATA SFF.
  	 */
  	.sg_tablesize		= ATA_MAX_PRD,
  	.dma_boundary		= SATA_RCAR_DMA_BOUNDARY,
163cf81d2   Vladimir Barinov   libata: add R-Car...
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
  };
  
  static struct ata_port_operations sata_rcar_port_ops = {
  	.inherits		= &ata_bmdma_port_ops,
  
  	.freeze			= sata_rcar_freeze,
  	.thaw			= sata_rcar_thaw,
  	.softreset		= sata_rcar_softreset,
  
  	.scr_read		= sata_rcar_scr_read,
  	.scr_write		= sata_rcar_scr_write,
  
  	.sff_dev_select		= sata_rcar_dev_select,
  	.sff_set_devctl		= sata_rcar_set_devctl,
  	.sff_check_status	= sata_rcar_check_status,
  	.sff_check_altstatus	= sata_rcar_check_altstatus,
  	.sff_tf_load		= sata_rcar_tf_load,
  	.sff_tf_read		= sata_rcar_tf_read,
  	.sff_exec_command	= sata_rcar_exec_command,
  	.sff_data_xfer		= sata_rcar_data_xfer,
  	.sff_drain_fifo		= sata_rcar_drain_fifo,
  
  	.qc_prep		= sata_rcar_qc_prep,
  
  	.bmdma_setup		= sata_rcar_bmdma_setup,
  	.bmdma_start		= sata_rcar_bmdma_start,
  	.bmdma_stop		= sata_rcar_bmdma_stop,
  	.bmdma_status		= sata_rcar_bmdma_status,
  };
52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
676
  static void sata_rcar_serr_interrupt(struct ata_port *ap)
163cf81d2   Vladimir Barinov   libata: add R-Car...
677
678
679
680
  {
  	struct sata_rcar_priv *priv = ap->host->private_data;
  	struct ata_eh_info *ehi = &ap->link.eh_info;
  	int freeze = 0;
163cf81d2   Vladimir Barinov   libata: add R-Car...
681
682
683
684
  	u32 serror;
  
  	serror = ioread32(priv->base + SCRSERR_REG);
  	if (!serror)
52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
685
  		return;
163cf81d2   Vladimir Barinov   libata: add R-Car...
686
687
688
689
690
691
692
693
694
695
696
697
698
  
  	DPRINTK("SError @host_intr: 0x%x
  ", serror);
  
  	/* first, analyze and record host port events */
  	ata_ehi_clear_desc(ehi);
  
  	if (serror & (SERR_DEV_XCHG | SERR_PHYRDY_CHG)) {
  		/* Setup a soft-reset EH action */
  		ata_ehi_hotplugged(ehi);
  		ata_ehi_push_desc(ehi, "%s", "hotplug");
  
  		freeze = serror & SERR_COMM_WAKE ? 0 : 1;
163cf81d2   Vladimir Barinov   libata: add R-Car...
699
700
701
702
703
704
705
  	}
  
  	/* freeze or abort */
  	if (freeze)
  		ata_port_freeze(ap);
  	else
  		ata_port_abort(ap);
163cf81d2   Vladimir Barinov   libata: add R-Car...
706
  }
52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
707
  static void sata_rcar_ata_interrupt(struct ata_port *ap)
163cf81d2   Vladimir Barinov   libata: add R-Car...
708
709
710
711
712
713
714
  {
  	struct ata_queued_cmd *qc;
  	int handled = 0;
  
  	qc = ata_qc_from_tag(ap, ap->link.active_tag);
  	if (qc)
  		handled |= ata_bmdma_port_intr(ap, qc);
52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
715
716
717
  	/* be sure to clear ATA interrupt */
  	if (!handled)
  		sata_rcar_check_status(ap);
163cf81d2   Vladimir Barinov   libata: add R-Car...
718
719
720
721
722
723
  }
  
  static irqreturn_t sata_rcar_interrupt(int irq, void *dev_instance)
  {
  	struct ata_host *host = dev_instance;
  	struct sata_rcar_priv *priv = host->private_data;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
724
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
725
  	unsigned int handled = 0;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
726
  	struct ata_port *ap;
163cf81d2   Vladimir Barinov   libata: add R-Car...
727
728
729
730
  	u32 sataintstat;
  	unsigned long flags;
  
  	spin_lock_irqsave(&host->lock, flags);
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
731
  	sataintstat = ioread32(base + SATAINTSTAT_REG);
52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
732
  	sataintstat &= SATA_RCAR_INT_MASK;
163cf81d2   Vladimir Barinov   libata: add R-Car...
733
734
735
  	if (!sataintstat)
  		goto done;
  	/* ack */
e207610ff   Wolfram Sang   ata: sata_rcar: r...
736
  	iowrite32(~sataintstat & priv->sataint_mask, base + SATAINTSTAT_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
737
738
739
740
  
  	ap = host->ports[0];
  
  	if (sataintstat & SATAINTSTAT_ATA)
52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
741
  		sata_rcar_ata_interrupt(ap);
163cf81d2   Vladimir Barinov   libata: add R-Car...
742
743
  
  	if (sataintstat & SATAINTSTAT_SERR)
52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
744
  		sata_rcar_serr_interrupt(ap);
163cf81d2   Vladimir Barinov   libata: add R-Car...
745

52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
746
  	handled = 1;
163cf81d2   Vladimir Barinov   libata: add R-Car...
747
748
749
750
751
752
753
754
755
756
757
  done:
  	spin_unlock_irqrestore(&host->lock, flags);
  
  	return IRQ_RETVAL(handled);
  }
  
  static void sata_rcar_setup_port(struct ata_host *host)
  {
  	struct ata_port *ap = host->ports[0];
  	struct ata_ioports *ioaddr = &ap->ioaddr;
  	struct sata_rcar_priv *priv = host->private_data;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
758
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
759
760
761
762
763
  
  	ap->ops		= &sata_rcar_port_ops;
  	ap->pio_mask	= ATA_PIO4;
  	ap->udma_mask	= ATA_UDMA6;
  	ap->flags	|= ATA_FLAG_SATA;
aa1cf2588   Simon Horman   ata: sata_rcar: D...
764
765
  	if (priv->type == RCAR_R8A7790_ES1_SATA)
  		ap->flags	|= ATA_FLAG_NO_DIPM;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
766
767
768
  	ioaddr->cmd_addr = base + SDATA_REG;
  	ioaddr->ctl_addr = base + SSDEVCON_REG;
  	ioaddr->scr_addr = base + SCRSSTS_REG;
163cf81d2   Vladimir Barinov   libata: add R-Car...
769
770
771
772
773
774
775
776
777
778
779
780
781
  	ioaddr->altstatus_addr = ioaddr->ctl_addr;
  
  	ioaddr->data_addr	= ioaddr->cmd_addr + (ATA_REG_DATA << 2);
  	ioaddr->error_addr	= ioaddr->cmd_addr + (ATA_REG_ERR << 2);
  	ioaddr->feature_addr	= ioaddr->cmd_addr + (ATA_REG_FEATURE << 2);
  	ioaddr->nsect_addr	= ioaddr->cmd_addr + (ATA_REG_NSECT << 2);
  	ioaddr->lbal_addr	= ioaddr->cmd_addr + (ATA_REG_LBAL << 2);
  	ioaddr->lbam_addr	= ioaddr->cmd_addr + (ATA_REG_LBAM << 2);
  	ioaddr->lbah_addr	= ioaddr->cmd_addr + (ATA_REG_LBAH << 2);
  	ioaddr->device_addr	= ioaddr->cmd_addr + (ATA_REG_DEVICE << 2);
  	ioaddr->status_addr	= ioaddr->cmd_addr + (ATA_REG_STATUS << 2);
  	ioaddr->command_addr	= ioaddr->cmd_addr + (ATA_REG_CMD << 2);
  }
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
782
  static void sata_rcar_init_module(struct sata_rcar_priv *priv)
163cf81d2   Vladimir Barinov   libata: add R-Car...
783
  {
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
784
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
785
  	u32 val;
163cf81d2   Vladimir Barinov   libata: add R-Car...
786
  	/* SATA-IP reset state */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
787
  	val = ioread32(base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
788
  	val |= ATAPI_CONTROL1_RESET;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
789
  	iowrite32(val, base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
790
791
  
  	/* ISM mode, PRD mode, DTEND flag at bit 0 */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
792
  	val = ioread32(base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
793
794
795
  	val |= ATAPI_CONTROL1_ISM;
  	val |= ATAPI_CONTROL1_DESE;
  	val |= ATAPI_CONTROL1_DTA32M;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
796
  	iowrite32(val, base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
797
798
  
  	/* Release the SATA-IP from the reset state */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
799
  	val = ioread32(base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
800
  	val &= ~ATAPI_CONTROL1_RESET;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
801
  	iowrite32(val, base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
802
803
  
  	/* ack and mask */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
804
  	iowrite32(0, base + SATAINTSTAT_REG);
e207610ff   Wolfram Sang   ata: sata_rcar: r...
805
  	iowrite32(priv->sataint_mask, base + SATAINTMASK_REG);
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
806

163cf81d2   Vladimir Barinov   libata: add R-Car...
807
  	/* enable interrupts */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
808
  	iowrite32(ATAPI_INT_ENABLE_SATAINT, base + ATAPI_INT_ENABLE_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
809
  }
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
810
811
812
  static void sata_rcar_init_controller(struct ata_host *host)
  {
  	struct sata_rcar_priv *priv = host->private_data;
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
813

e207610ff   Wolfram Sang   ata: sata_rcar: r...
814
  	priv->sataint_mask = SATAINTMASK_ALL_GEN2;
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
815
816
817
  	/* reset and setup phy */
  	switch (priv->type) {
  	case RCAR_GEN1_SATA:
e207610ff   Wolfram Sang   ata: sata_rcar: r...
818
  		priv->sataint_mask = SATAINTMASK_ALL_GEN1;
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
819
820
821
  		sata_rcar_gen1_phy_init(priv);
  		break;
  	case RCAR_GEN2_SATA:
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
822
823
824
  	case RCAR_R8A7790_ES1_SATA:
  		sata_rcar_gen2_phy_init(priv);
  		break;
96b954895   Masaharu Hayakawa   ata: sata_rcar: e...
825
826
  	case RCAR_GEN3_SATA:
  		break;
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
827
828
829
830
831
832
833
834
  	default:
  		dev_warn(host->dev, "SATA phy is not initialized
  ");
  		break;
  	}
  
  	sata_rcar_init_module(priv);
  }
a5893870f   Arvind Yadav   ata: sata_rcar: m...
835
  static const struct of_device_id sata_rcar_match[] = {
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
836
837
838
839
840
841
842
843
844
845
846
847
848
849
  	{
  		/* Deprecated by "renesas,sata-r8a7779" */
  		.compatible = "renesas,rcar-sata",
  		.data = (void *)RCAR_GEN1_SATA,
  	},
  	{
  		.compatible = "renesas,sata-r8a7779",
  		.data = (void *)RCAR_GEN1_SATA,
  	},
  	{
  		.compatible = "renesas,sata-r8a7790",
  		.data = (void *)RCAR_GEN2_SATA
  	},
  	{
aa1cf2588   Simon Horman   ata: sata_rcar: D...
850
851
852
853
  		.compatible = "renesas,sata-r8a7790-es1",
  		.data = (void *)RCAR_R8A7790_ES1_SATA
  	},
  	{
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
854
855
856
  		.compatible = "renesas,sata-r8a7791",
  		.data = (void *)RCAR_GEN2_SATA
  	},
e35b98849   Koji Matsuoka   ata: sata_rcar: A...
857
858
859
860
  	{
  		.compatible = "renesas,sata-r8a7793",
  		.data = (void *)RCAR_GEN2_SATA
  	},
fec7bc433   Kouei Abe   sata_rcar: Add co...
861
862
  	{
  		.compatible = "renesas,sata-r8a7795",
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
863
  		.data = (void *)RCAR_GEN3_SATA
fec7bc433   Kouei Abe   sata_rcar: Add co...
864
  	},
6ac1d1532   Simon Horman   ata: sata_rcar: a...
865
866
867
868
869
870
  	{
  		.compatible = "renesas,rcar-gen2-sata",
  		.data = (void *)RCAR_GEN2_SATA
  	},
  	{
  		.compatible = "renesas,rcar-gen3-sata",
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
871
  		.data = (void *)RCAR_GEN3_SATA
6ac1d1532   Simon Horman   ata: sata_rcar: a...
872
  	},
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
873
874
875
  	{ },
  };
  MODULE_DEVICE_TABLE(of, sata_rcar_match);
163cf81d2   Vladimir Barinov   libata: add R-Car...
876
877
  static int sata_rcar_probe(struct platform_device *pdev)
  {
c01e229f2   Geert Uytterhoeven   ata: sata_rcar: P...
878
  	struct device *dev = &pdev->dev;
163cf81d2   Vladimir Barinov   libata: add R-Car...
879
880
881
882
883
  	struct ata_host *host;
  	struct sata_rcar_priv *priv;
  	struct resource *mem;
  	int irq;
  	int ret = 0;
163cf81d2   Vladimir Barinov   libata: add R-Car...
884
  	irq = platform_get_irq(pdev, 0);
9f83cfdb1   Sergei Shtylyov   sata_rcar: fix de...
885
886
887
  	if (irq < 0)
  		return irq;
  	if (!irq)
163cf81d2   Vladimir Barinov   libata: add R-Car...
888
  		return -EINVAL;
c01e229f2   Geert Uytterhoeven   ata: sata_rcar: P...
889
  	priv = devm_kzalloc(dev, sizeof(struct sata_rcar_priv), GFP_KERNEL);
163cf81d2   Vladimir Barinov   libata: add R-Car...
890
891
  	if (!priv)
  		return -ENOMEM;
c01e229f2   Geert Uytterhoeven   ata: sata_rcar: P...
892
  	priv->type = (enum sata_rcar_type)of_device_get_match_data(dev);
5dc63fdcc   Arvind Yadav   ata: sata_rcar: H...
893

1ecd34ddf   Geert Uytterhoeven   ata: sata_rcar: A...
894
895
896
897
  	pm_runtime_enable(dev);
  	ret = pm_runtime_get_sync(dev);
  	if (ret < 0)
  		goto err_pm_disable;
163cf81d2   Vladimir Barinov   libata: add R-Car...
898

c01e229f2   Geert Uytterhoeven   ata: sata_rcar: P...
899
  	host = ata_host_alloc(dev, 1);
163cf81d2   Vladimir Barinov   libata: add R-Car...
900
  	if (!host) {
163cf81d2   Vladimir Barinov   libata: add R-Car...
901
  		ret = -ENOMEM;
1ecd34ddf   Geert Uytterhoeven   ata: sata_rcar: A...
902
  		goto err_pm_put;
163cf81d2   Vladimir Barinov   libata: add R-Car...
903
904
905
  	}
  
  	host->private_data = priv;
4a9b7f9f2   Julia Lawall   drivers/ata/sata_...
906
  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
c01e229f2   Geert Uytterhoeven   ata: sata_rcar: P...
907
  	priv->base = devm_ioremap_resource(dev, mem);
2de1d5e15   Sachin Kamat   sata_rcar: Conver...
908
909
  	if (IS_ERR(priv->base)) {
  		ret = PTR_ERR(priv->base);
1ecd34ddf   Geert Uytterhoeven   ata: sata_rcar: A...
910
  		goto err_pm_put;
163cf81d2   Vladimir Barinov   libata: add R-Car...
911
912
913
914
915
916
917
918
919
920
921
922
  	}
  
  	/* setup port */
  	sata_rcar_setup_port(host);
  
  	/* initialize host controller */
  	sata_rcar_init_controller(host);
  
  	ret = ata_host_activate(host, irq, sata_rcar_interrupt, 0,
  				&sata_rcar_sht);
  	if (!ret)
  		return 0;
1ecd34ddf   Geert Uytterhoeven   ata: sata_rcar: A...
923
924
925
926
  err_pm_put:
  	pm_runtime_put(dev);
  err_pm_disable:
  	pm_runtime_disable(dev);
163cf81d2   Vladimir Barinov   libata: add R-Car...
927
928
929
930
931
  	return ret;
  }
  
  static int sata_rcar_remove(struct platform_device *pdev)
  {
d89995db5   Jingoo Han   ata: use platform...
932
  	struct ata_host *host = platform_get_drvdata(pdev);
163cf81d2   Vladimir Barinov   libata: add R-Car...
933
  	struct sata_rcar_priv *priv = host->private_data;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
934
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
935
936
937
938
  
  	ata_host_detach(host);
  
  	/* disable interrupts */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
939
  	iowrite32(0, base + ATAPI_INT_ENABLE_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
940
  	/* ack and mask */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
941
  	iowrite32(0, base + SATAINTSTAT_REG);
e207610ff   Wolfram Sang   ata: sata_rcar: r...
942
  	iowrite32(priv->sataint_mask, base + SATAINTMASK_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
943

1ecd34ddf   Geert Uytterhoeven   ata: sata_rcar: A...
944
945
  	pm_runtime_put(&pdev->dev);
  	pm_runtime_disable(&pdev->dev);
163cf81d2   Vladimir Barinov   libata: add R-Car...
946
947
948
  
  	return 0;
  }
58eb8cd56   Bartlomiej Zolnierkiewicz   ata: use CONFIG_P...
949
  #ifdef CONFIG_PM_SLEEP
163cf81d2   Vladimir Barinov   libata: add R-Car...
950
951
952
953
  static int sata_rcar_suspend(struct device *dev)
  {
  	struct ata_host *host = dev_get_drvdata(dev);
  	struct sata_rcar_priv *priv = host->private_data;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
954
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
955
956
957
958
959
  	int ret;
  
  	ret = ata_host_suspend(host, PMSG_SUSPEND);
  	if (!ret) {
  		/* disable interrupts */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
960
  		iowrite32(0, base + ATAPI_INT_ENABLE_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
961
  		/* mask */
e207610ff   Wolfram Sang   ata: sata_rcar: r...
962
  		iowrite32(priv->sataint_mask, base + SATAINTMASK_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
963

1ecd34ddf   Geert Uytterhoeven   ata: sata_rcar: A...
964
  		pm_runtime_put(dev);
163cf81d2   Vladimir Barinov   libata: add R-Car...
965
966
967
968
969
970
971
972
973
  	}
  
  	return ret;
  }
  
  static int sata_rcar_resume(struct device *dev)
  {
  	struct ata_host *host = dev_get_drvdata(dev);
  	struct sata_rcar_priv *priv = host->private_data;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
974
  	void __iomem *base = priv->base;
5dc63fdcc   Arvind Yadav   ata: sata_rcar: H...
975
  	int ret;
163cf81d2   Vladimir Barinov   libata: add R-Car...
976

1ecd34ddf   Geert Uytterhoeven   ata: sata_rcar: A...
977
978
  	ret = pm_runtime_get_sync(dev);
  	if (ret < 0)
5dc63fdcc   Arvind Yadav   ata: sata_rcar: H...
979
  		return ret;
163cf81d2   Vladimir Barinov   libata: add R-Car...
980

da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
981
  	if (priv->type == RCAR_GEN3_SATA) {
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
982
983
984
985
  		sata_rcar_init_module(priv);
  	} else {
  		/* ack and mask */
  		iowrite32(0, base + SATAINTSTAT_REG);
e207610ff   Wolfram Sang   ata: sata_rcar: r...
986
  		iowrite32(priv->sataint_mask, base + SATAINTMASK_REG);
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
987
988
989
990
991
  
  		/* enable interrupts */
  		iowrite32(ATAPI_INT_ENABLE_SATAINT,
  			  base + ATAPI_INT_ENABLE_REG);
  	}
163cf81d2   Vladimir Barinov   libata: add R-Car...
992
993
994
995
996
  
  	ata_host_resume(host);
  
  	return 0;
  }
5bc27ef72   Mikhail Ulyanov   sata_rcar: extend...
997
998
999
  static int sata_rcar_restore(struct device *dev)
  {
  	struct ata_host *host = dev_get_drvdata(dev);
5dc63fdcc   Arvind Yadav   ata: sata_rcar: H...
1000
  	int ret;
5bc27ef72   Mikhail Ulyanov   sata_rcar: extend...
1001

1ecd34ddf   Geert Uytterhoeven   ata: sata_rcar: A...
1002
1003
  	ret = pm_runtime_get_sync(dev);
  	if (ret < 0)
5dc63fdcc   Arvind Yadav   ata: sata_rcar: H...
1004
  		return ret;
5bc27ef72   Mikhail Ulyanov   sata_rcar: extend...
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
  
  	sata_rcar_setup_port(host);
  
  	/* initialize host controller */
  	sata_rcar_init_controller(host);
  
  	ata_host_resume(host);
  
  	return 0;
  }
163cf81d2   Vladimir Barinov   libata: add R-Car...
1015
1016
1017
  static const struct dev_pm_ops sata_rcar_pm_ops = {
  	.suspend	= sata_rcar_suspend,
  	.resume		= sata_rcar_resume,
5bc27ef72   Mikhail Ulyanov   sata_rcar: extend...
1018
1019
1020
1021
  	.freeze		= sata_rcar_suspend,
  	.thaw		= sata_rcar_resume,
  	.poweroff	= sata_rcar_suspend,
  	.restore	= sata_rcar_restore,
163cf81d2   Vladimir Barinov   libata: add R-Car...
1022
1023
  };
  #endif
163cf81d2   Vladimir Barinov   libata: add R-Car...
1024
1025
1026
1027
1028
  static struct platform_driver sata_rcar_driver = {
  	.probe		= sata_rcar_probe,
  	.remove		= sata_rcar_remove,
  	.driver = {
  		.name		= DRV_NAME,
163cf81d2   Vladimir Barinov   libata: add R-Car...
1029
  		.of_match_table	= sata_rcar_match,
58eb8cd56   Bartlomiej Zolnierkiewicz   ata: use CONFIG_P...
1030
  #ifdef CONFIG_PM_SLEEP
163cf81d2   Vladimir Barinov   libata: add R-Car...
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
  		.pm		= &sata_rcar_pm_ops,
  #endif
  	},
  };
  
  module_platform_driver(sata_rcar_driver);
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Vladimir Barinov");
  MODULE_DESCRIPTION("Renesas R-Car SATA controller low level driver");