Blame view

drivers/ata/sata_rcar.c 26.8 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)
df9c59098   Geert Uytterhoeven   ata: sata_rcar: F...
122
  #define SATA_RCAR_DMA_BOUNDARY		0x1FFFFFFFUL
8bfbeed58   Sergei Shtylyov   sata_rcar: correc...
123

e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  /* 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 ...
146
  	RCAR_GEN3_SATA,
aa1cf2588   Simon Horman   ata: sata_rcar: D...
147
  	RCAR_R8A7790_ES1_SATA,
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
148
  };
163cf81d2   Vladimir Barinov   libata: add R-Car...
149
150
  struct sata_rcar_priv {
  	void __iomem *base;
e207610ff   Wolfram Sang   ata: sata_rcar: r...
151
  	u32 sataint_mask;
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
152
  	enum sata_rcar_type type;
163cf81d2   Vladimir Barinov   libata: add R-Car...
153
  };
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
154
  static void sata_rcar_gen1_phy_preinit(struct sata_rcar_priv *priv)
163cf81d2   Vladimir Barinov   libata: add R-Car...
155
  {
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
156
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
157
  	/* idle state */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
158
  	iowrite32(0, base + SATAPHYADDR_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
159
  	/* reset */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
160
  	iowrite32(SATAPHYRESET_PHYRST, base + SATAPHYRESET_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
161
162
  	udelay(10);
  	/* deassert reset */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
163
  	iowrite32(0, base + SATAPHYRESET_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
164
  }
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
165
166
  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...
167
  {
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
168
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
169
170
171
  	int timeout;
  
  	/* deassert reset */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
172
  	iowrite32(0, base + SATAPHYRESET_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
173
  	/* lane 1 */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
174
  	iowrite32(SATAPHYACCEN_PHYLANE, base + SATAPHYACCEN_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
175
  	/* write phy register value */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
176
  	iowrite32(val, base + SATAPHYWDATA_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
177
178
179
180
  	/* set register group */
  	if (group)
  		reg |= SATAPHYADDR_PHYRATEMODE;
  	/* write command */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
181
  	iowrite32(SATAPHYADDR_PHYCMD_WRITE | reg, base + SATAPHYADDR_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
182
183
  	/* wait for ack */
  	for (timeout = 0; timeout < 100; timeout++) {
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
184
  		val = ioread32(base + SATAPHYACK_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
185
186
187
188
189
190
191
  		if (val & SATAPHYACK_PHYACK)
  			break;
  	}
  	if (timeout >= 100)
  		pr_err("%s timeout
  ", __func__);
  	/* idle state */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
192
  	iowrite32(0, base + SATAPHYADDR_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
193
  }
e67adb4e6   Valentine Barshak   sata_rcar: Add R-...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  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...
216
217
218
219
220
  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...
221
  	iowrite32(priv->sataint_mask, priv->base + SATAINTMASK_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
222
223
224
225
226
227
228
  
  	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...
229
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
230
231
  
  	/* ack */
5a0a6a4f1   Tejun Heo   Merge branch 'lib...
232
  	iowrite32(~(u32)SATA_RCAR_INT_MASK, base + SATAINTSTAT_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
233
234
235
236
  
  	ata_sff_thaw(ap);
  
  	/* unmask */
e207610ff   Wolfram Sang   ata: sata_rcar: r...
237
  	iowrite32(priv->sataint_mask & ~SATA_RCAR_INT_MASK, base + SATAINTMASK_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
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
449
  }
  
  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 ...
450
  static unsigned int sata_rcar_data_xfer(struct ata_queued_cmd *qc,
163cf81d2   Vladimir Barinov   libata: add R-Car...
451
452
453
  					      unsigned char *buf,
  					      unsigned int buflen, int rw)
  {
989e0aac1   Bartlomiej Zolnierkiewicz   ata: pass queued ...
454
  	struct ata_port *ap = qc->dev->link->ap;
163cf81d2   Vladimir Barinov   libata: add R-Car...
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
533
  	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...
534
  	unsigned int si;
163cf81d2   Vladimir Barinov   libata: add R-Car...
535

163cf81d2   Vladimir Barinov   libata: add R-Car...
536
  	for_each_sg(qc->sg, sg, qc->n_elem, si) {
333279c82   Sergei Shtylyov   sata_rcar: kill s...
537
  		u32 addr, sg_len;
163cf81d2   Vladimir Barinov   libata: add R-Car...
538
539
540
541
542
543
544
  
  		/*
  		 * 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...
545
546
547
548
  		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...
549
550
551
  	}
  
  	/* end-of-table flag */
333279c82   Sergei Shtylyov   sata_rcar: kill s...
552
  	prd[si - 1].addr |= cpu_to_le32(SATA_RCAR_DTEND);
163cf81d2   Vladimir Barinov   libata: add R-Car...
553
  }
95364f367   Jiri Slaby   ata: make qc_prep...
554
  static enum ata_completion_errors sata_rcar_qc_prep(struct ata_queued_cmd *qc)
163cf81d2   Vladimir Barinov   libata: add R-Car...
555
556
  {
  	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
95364f367   Jiri Slaby   ata: make qc_prep...
557
  		return AC_ERR_OK;
163cf81d2   Vladimir Barinov   libata: add R-Car...
558
559
  
  	sata_rcar_bmdma_fill_sg(qc);
95364f367   Jiri Slaby   ata: make qc_prep...
560
561
  
  	return AC_ERR_OK;
163cf81d2   Vladimir Barinov   libata: add R-Car...
562
563
564
565
566
567
  }
  
  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...
568
  	struct sata_rcar_priv *priv = ap->host->private_data;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
569
570
  	void __iomem *base = priv->base;
  	u32 dmactl;
163cf81d2   Vladimir Barinov   libata: add R-Car...
571
572
573
  
  	/* load PRD table addr. */
  	mb();   /* make sure PRD table writes are visible to controller */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
574
  	iowrite32(ap->bmdma_prd_dma, base + ATAPI_DTB_ADR_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
575
576
  
  	/* specify data direction, triple-check start bit is clear */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
577
  	dmactl = ioread32(base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
578
579
580
581
582
583
584
  	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...
585
  	iowrite32(dmactl, base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
586
587
588
589
590
591
592
593
  
  	/* 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...
594
  	struct sata_rcar_priv *priv = ap->host->private_data;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
595
596
  	void __iomem *base = priv->base;
  	u32 dmactl;
163cf81d2   Vladimir Barinov   libata: add R-Car...
597
598
  
  	/* start host DMA transaction */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
599
  	dmactl = ioread32(base + ATAPI_CONTROL1_REG);
df7e131f6   Sergei Shtylyov   sata_rcar: clear ...
600
  	dmactl &= ~ATAPI_CONTROL1_STOP;
163cf81d2   Vladimir Barinov   libata: add R-Car...
601
  	dmactl |= ATAPI_CONTROL1_START;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
602
  	iowrite32(dmactl, base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
603
604
605
606
607
608
  }
  
  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...
609
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
610
611
612
  	u32 dmactl;
  
  	/* force termination of DMA transfer if active */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
613
  	dmactl = ioread32(base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
614
615
616
  	if (dmactl & ATAPI_CONTROL1_START) {
  		dmactl &= ~ATAPI_CONTROL1_START;
  		dmactl |= ATAPI_CONTROL1_STOP;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
617
  		iowrite32(dmactl, base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
618
619
620
621
622
623
624
625
626
  	}
  
  	/* 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...
627
  	u8 host_stat = 0;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
628
  	u32 status;
163cf81d2   Vladimir Barinov   libata: add R-Car...
629
630
631
632
633
634
635
636
637
638
639
  
  	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...
640
641
642
643
644
645
646
647
  	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...
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
676
  };
  
  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...
677
  static void sata_rcar_serr_interrupt(struct ata_port *ap)
163cf81d2   Vladimir Barinov   libata: add R-Car...
678
679
680
681
  {
  	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...
682
683
684
685
  	u32 serror;
  
  	serror = ioread32(priv->base + SCRSERR_REG);
  	if (!serror)
52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
686
  		return;
163cf81d2   Vladimir Barinov   libata: add R-Car...
687
688
689
690
691
692
693
694
695
696
697
698
699
  
  	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...
700
701
702
703
704
705
706
  	}
  
  	/* freeze or abort */
  	if (freeze)
  		ata_port_freeze(ap);
  	else
  		ata_port_abort(ap);
163cf81d2   Vladimir Barinov   libata: add R-Car...
707
  }
52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
708
  static void sata_rcar_ata_interrupt(struct ata_port *ap)
163cf81d2   Vladimir Barinov   libata: add R-Car...
709
710
711
712
713
714
715
  {
  	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...
716
717
718
  	/* be sure to clear ATA interrupt */
  	if (!handled)
  		sata_rcar_check_status(ap);
163cf81d2   Vladimir Barinov   libata: add R-Car...
719
720
721
722
723
724
  }
  
  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...
725
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
726
  	unsigned int handled = 0;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
727
  	struct ata_port *ap;
163cf81d2   Vladimir Barinov   libata: add R-Car...
728
729
730
731
  	u32 sataintstat;
  	unsigned long flags;
  
  	spin_lock_irqsave(&host->lock, flags);
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
732
  	sataintstat = ioread32(base + SATAINTSTAT_REG);
52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
733
  	sataintstat &= SATA_RCAR_INT_MASK;
163cf81d2   Vladimir Barinov   libata: add R-Car...
734
735
736
  	if (!sataintstat)
  		goto done;
  	/* ack */
e207610ff   Wolfram Sang   ata: sata_rcar: r...
737
  	iowrite32(~sataintstat & priv->sataint_mask, base + SATAINTSTAT_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
738
739
740
741
  
  	ap = host->ports[0];
  
  	if (sataintstat & SATAINTSTAT_ATA)
52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
742
  		sata_rcar_ata_interrupt(ap);
163cf81d2   Vladimir Barinov   libata: add R-Car...
743
744
  
  	if (sataintstat & SATAINTSTAT_SERR)
52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
745
  		sata_rcar_serr_interrupt(ap);
163cf81d2   Vladimir Barinov   libata: add R-Car...
746

52a2a1087   Sergei Shtylyov   sata_rcar: fix in...
747
  	handled = 1;
163cf81d2   Vladimir Barinov   libata: add R-Car...
748
749
750
751
752
753
754
755
756
757
758
  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...
759
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
760
761
762
763
764
  
  	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...
765
766
  	if (priv->type == RCAR_R8A7790_ES1_SATA)
  		ap->flags	|= ATA_FLAG_NO_DIPM;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
767
768
769
  	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...
770
771
772
773
774
775
776
777
778
779
780
781
782
  	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 ...
783
  static void sata_rcar_init_module(struct sata_rcar_priv *priv)
163cf81d2   Vladimir Barinov   libata: add R-Car...
784
  {
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
785
  	void __iomem *base = priv->base;
163cf81d2   Vladimir Barinov   libata: add R-Car...
786
  	u32 val;
163cf81d2   Vladimir Barinov   libata: add R-Car...
787
  	/* SATA-IP reset state */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
788
  	val = ioread32(base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
789
  	val |= ATAPI_CONTROL1_RESET;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
790
  	iowrite32(val, base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
791
792
  
  	/* ISM mode, PRD mode, DTEND flag at bit 0 */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
793
  	val = ioread32(base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
794
795
796
  	val |= ATAPI_CONTROL1_ISM;
  	val |= ATAPI_CONTROL1_DESE;
  	val |= ATAPI_CONTROL1_DTA32M;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
797
  	iowrite32(val, base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
798
799
  
  	/* Release the SATA-IP from the reset state */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
800
  	val = ioread32(base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
801
  	val &= ~ATAPI_CONTROL1_RESET;
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
802
  	iowrite32(val, base + ATAPI_CONTROL1_REG);
163cf81d2   Vladimir Barinov   libata: add R-Car...
803
804
  
  	/* ack and mask */
1b20f6a9a   Sergei Shtylyov   sata_rcar: add 'b...
805
  	iowrite32(0, base + SATAINTSTAT_REG);
e207610ff   Wolfram Sang   ata: sata_rcar: r...
806
  	iowrite32(priv->sataint_mask, base + SATAINTMASK_REG);
da77d76b9   Khiem Nguyen   sata_rcar: Reset ...
807

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

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

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

c01e229f2   Geert Uytterhoeven   ata: sata_rcar: P...
900
  	host = ata_host_alloc(dev, 1);
163cf81d2   Vladimir Barinov   libata: add R-Car...
901
  	if (!host) {
163cf81d2   Vladimir Barinov   libata: add R-Car...
902
  		ret = -ENOMEM;
1ecd34ddf   Geert Uytterhoeven   ata: sata_rcar: A...
903
  		goto err_pm_put;
163cf81d2   Vladimir Barinov   libata: add R-Car...
904
905
906
  	}
  
  	host->private_data = priv;
4a9b7f9f2   Julia Lawall   drivers/ata/sata_...
907
  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
c01e229f2   Geert Uytterhoeven   ata: sata_rcar: P...
908
  	priv->base = devm_ioremap_resource(dev, mem);
2de1d5e15   Sachin Kamat   sata_rcar: Conver...
909
910
  	if (IS_ERR(priv->base)) {
  		ret = PTR_ERR(priv->base);
1ecd34ddf   Geert Uytterhoeven   ata: sata_rcar: A...
911
  		goto err_pm_put;
163cf81d2   Vladimir Barinov   libata: add R-Car...
912
913
914
915
916
917
918
919
920
921
922
923
  	}
  
  	/* 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...
924
925
  err_pm_put:
  	pm_runtime_put(dev);
1ecd34ddf   Geert Uytterhoeven   ata: sata_rcar: A...
926
  	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
  	ret = pm_runtime_get_sync(dev);
eea123886   Navid Emamdoost   sata_rcar: handle...
978
979
  	if (ret < 0) {
  		pm_runtime_put(dev);
5dc63fdcc   Arvind Yadav   ata: sata_rcar: H...
980
  		return ret;
eea123886   Navid Emamdoost   sata_rcar: handle...
981
  	}
163cf81d2   Vladimir Barinov   libata: add R-Car...
982

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

1ecd34ddf   Geert Uytterhoeven   ata: sata_rcar: A...
1004
  	ret = pm_runtime_get_sync(dev);
eea123886   Navid Emamdoost   sata_rcar: handle...
1005
1006
  	if (ret < 0) {
  		pm_runtime_put(dev);
5dc63fdcc   Arvind Yadav   ata: sata_rcar: H...
1007
  		return ret;
eea123886   Navid Emamdoost   sata_rcar: handle...
1008
  	}
5bc27ef72   Mikhail Ulyanov   sata_rcar: extend...
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
  
  	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...
1019
1020
1021
  static const struct dev_pm_ops sata_rcar_pm_ops = {
  	.suspend	= sata_rcar_suspend,
  	.resume		= sata_rcar_resume,
5bc27ef72   Mikhail Ulyanov   sata_rcar: extend...
1022
1023
1024
1025
  	.freeze		= sata_rcar_suspend,
  	.thaw		= sata_rcar_resume,
  	.poweroff	= sata_rcar_suspend,
  	.restore	= sata_rcar_restore,
163cf81d2   Vladimir Barinov   libata: add R-Car...
1026
1027
  };
  #endif
163cf81d2   Vladimir Barinov   libata: add R-Car...
1028
1029
1030
1031
1032
  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...
1033
  		.of_match_table	= sata_rcar_match,
58eb8cd56   Bartlomiej Zolnierkiewicz   ata: use CONFIG_P...
1034
  #ifdef CONFIG_PM_SLEEP
163cf81d2   Vladimir Barinov   libata: add R-Car...
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
  		.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");