Blame view

drivers/block/mvsata_ide.c 4.74 KB
39419ce58   Albert Aribaud   ide: add mvsata_i...
1
  /*
57b4bce99   Albert ARIBAUD   Replace obsolete ...
2
   * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net>
39419ce58   Albert Aribaud   ide: add mvsata_i...
3
   *
57b4bce99   Albert ARIBAUD   Replace obsolete ...
4
   * Written-by: Albert ARIBAUD <albert.u.boot@aribaud.net>
39419ce58   Albert Aribaud   ide: add mvsata_i...
5
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
6
   * SPDX-License-Identifier:	GPL-2.0+
39419ce58   Albert Aribaud   ide: add mvsata_i...
7
8
9
10
11
12
13
14
15
16
17
18
19
   */
  
  #include <common.h>
  #include <asm/io.h>
  
  #if defined(CONFIG_ORION5X)
  #include <asm/arch/orion5x.h>
  #elif defined(CONFIG_KIRKWOOD)
  #include <asm/arch/kirkwood.h>
  #endif
  
  /* SATA port registers */
  struct mvsata_port_registers {
70c55f5ab   Michael Walle   mvsata: issue har...
20
21
22
  	u32 reserved0[10];
  	u32 edma_cmd;
  	u32 reserved1[181];
39419ce58   Albert Aribaud   ide: add mvsata_i...
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  	/* offset 0x300 : ATA Interface registers */
  	u32 sstatus;
  	u32 serror;
  	u32 scontrol;
  	u32 ltmode;
  	u32 phymode3;
  	u32 phymode4;
  	u32 reserved2[5];
  	u32 phymode1;
  	u32 phymode2;
  	u32 bist_cr;
  	u32 bist_dw1;
  	u32 bist_dw2;
  	u32 serrorintrmask;
  };
  
  /*
   * Sanity checks:
   * - to compile at all, we need CONFIG_SYS_ATA_BASE_ADDR.
   * - for ide_preinit to make sense, we need at least one of
c08349e77   Gray Remlin   mvsata_ide.c: Cor...
43
44
   *   CONFIG_SYS_ATA_IDE0_OFFSET or CONFIG_SYS_ATA_IDE1_OFFSET;
   * - for ide_preinit to be called, we need CONFIG_IDE_PREINIT.
39419ce58   Albert Aribaud   ide: add mvsata_i...
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
   * Fail with an explanation message if these conditions are not met.
   * This is particularly important for CONFIG_IDE_PREINIT, because
   * its lack would not cause a build error.
   */
  
  #if !defined(CONFIG_SYS_ATA_BASE_ADDR)
  #error CONFIG_SYS_ATA_BASE_ADDR must be defined
  #elif !defined(CONFIG_SYS_ATA_IDE0_OFFSET) \
     && !defined(CONFIG_SYS_ATA_IDE1_OFFSET)
  #error CONFIG_SYS_ATA_IDE0_OFFSET or CONFIG_SYS_ATA_IDE1_OFFSET \
     must be defined
  #elif !defined(CONFIG_IDE_PREINIT)
  #error CONFIG_IDE_PREINIT must be defined
  #endif
  
  /*
   * Masks and values for SControl DETection and Interface Power Management,
   * and for SStatus DETection.
   */
70c55f5ab   Michael Walle   mvsata: issue har...
64
  #define MVSATA_EDMA_CMD_ATA_RST		0x00000004
39419ce58   Albert Aribaud   ide: add mvsata_i...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  #define MVSATA_SCONTROL_DET_MASK		0x0000000F
  #define MVSATA_SCONTROL_DET_NONE		0x00000000
  #define MVSATA_SCONTROL_DET_INIT		0x00000001
  #define MVSATA_SCONTROL_IPM_MASK		0x00000F00
  #define MVSATA_SCONTROL_IPM_NO_LP_ALLOWED	0x00000300
  #define MVSATA_SCONTROL_MASK \
  	(MVSATA_SCONTROL_DET_MASK|MVSATA_SCONTROL_IPM_MASK)
  #define MVSATA_PORT_INIT \
  	(MVSATA_SCONTROL_DET_INIT|MVSATA_SCONTROL_IPM_NO_LP_ALLOWED)
  #define MVSATA_PORT_USE \
  	(MVSATA_SCONTROL_DET_NONE|MVSATA_SCONTROL_IPM_NO_LP_ALLOWED)
  #define MVSATA_SSTATUS_DET_MASK			0x0000000F
  #define MVSATA_SSTATUS_DET_DEVCOMM		0x00000003
  
  /*
d3497138f   Albert Aribaud   mvsata_ide: adjus...
80
81
82
83
84
85
86
87
88
89
90
91
   * Status codes to return to client callers. Currently, callers ignore
   * exact value and only care for zero or nonzero, so no need to make this
   * public, it is only #define'd for clarity.
   * If/when standard negative codes are implemented in U-boot, then these
   * #defines should be moved to, or replaced by ones from, the common list
   * of status codes.
   */
  
  #define MVSATA_STATUS_OK	0
  #define MVSATA_STATUS_TIMEOUT	-1
  
  /*
39419ce58   Albert Aribaud   ide: add mvsata_i...
92
93
94
95
96
   * Initialize one MVSATAHC port: set SControl's IPM to "always active"
   * and DET to "reset", then wait for SStatus's DET to become "device and
   * comm ok" (or time out after 50 us if no device), then set SControl's
   * DET back to "no action".
   */
d3497138f   Albert Aribaud   mvsata_ide: adjus...
97
  static int mvsata_ide_initialize_port(struct mvsata_port_registers *port)
39419ce58   Albert Aribaud   ide: add mvsata_i...
98
99
100
  {
  	u32 control;
  	u32 status;
d3497138f   Albert Aribaud   mvsata_ide: adjus...
101
  	u32 timeleft = 10000; /* wait at most 10 ms for SATA reset to complete */
39419ce58   Albert Aribaud   ide: add mvsata_i...
102

70c55f5ab   Michael Walle   mvsata: issue har...
103
104
105
106
  	/* Hard reset */
  	writel(MVSATA_EDMA_CMD_ATA_RST, &port->edma_cmd);
  	udelay(25); /* taken from original marvell port */
  	writel(0, &port->edma_cmd);
d3497138f   Albert Aribaud   mvsata_ide: adjus...
107
  	/* Set control IPM to 3 (no low power) and DET to 1 (initialize) */
39419ce58   Albert Aribaud   ide: add mvsata_i...
108
109
110
  	control = readl(&port->scontrol);
  	control = (control & ~MVSATA_SCONTROL_MASK) | MVSATA_PORT_INIT;
  	writel(control, &port->scontrol);
d3497138f   Albert Aribaud   mvsata_ide: adjus...
111
112
113
114
115
  	/* Toggle control DET back to 0 (normal operation) */
  	control = (control & ~MVSATA_SCONTROL_MASK) | MVSATA_PORT_USE;
  	writel(control, &port->scontrol);
  	/* wait for status DET to become 3 (device and communication OK) */
  	while (--timeleft) {
39419ce58   Albert Aribaud   ide: add mvsata_i...
116
117
118
119
120
  		status = readl(&port->sstatus) & MVSATA_SSTATUS_DET_MASK;
  		if (status == MVSATA_SSTATUS_DET_DEVCOMM)
  			break;
  		udelay(1);
  	}
d3497138f   Albert Aribaud   mvsata_ide: adjus...
121
122
123
124
  	/* return success or time-out error depending on time left */
  	if (!timeleft)
  		return MVSATA_STATUS_TIMEOUT;
  	return MVSATA_STATUS_OK;
39419ce58   Albert Aribaud   ide: add mvsata_i...
125
126
127
128
129
130
131
132
133
  }
  
  /*
   * ide_preinit() will be called by ide_init in cmd_ide.c and will
   * reset the MVSTATHC ports needed by the board.
   */
  
  int ide_preinit(void)
  {
2cb4fade0   Simon Guinot   mvsata: fix ide_p...
134
  	int ret = MVSATA_STATUS_TIMEOUT;
d3497138f   Albert Aribaud   mvsata_ide: adjus...
135
  	int status;
2cb4fade0   Simon Guinot   mvsata: fix ide_p...
136

39419ce58   Albert Aribaud   ide: add mvsata_i...
137
138
  	/* Enable ATA port 0 (could be SATA port 0 or 1) if declared */
  #if defined(CONFIG_SYS_ATA_IDE0_OFFSET)
d3497138f   Albert Aribaud   mvsata_ide: adjus...
139
  	status = mvsata_ide_initialize_port(
39419ce58   Albert Aribaud   ide: add mvsata_i...
140
141
  		(struct mvsata_port_registers *)
  		(CONFIG_SYS_ATA_BASE_ADDR + CONFIG_SYS_ATA_IDE0_OFFSET));
2cb4fade0   Simon Guinot   mvsata: fix ide_p...
142
143
  	if (status == MVSATA_STATUS_OK)
  		ret = MVSATA_STATUS_OK;
39419ce58   Albert Aribaud   ide: add mvsata_i...
144
145
146
  #endif
  	/* Enable ATA port 1 (could be SATA port 0 or 1) if declared */
  #if defined(CONFIG_SYS_ATA_IDE1_OFFSET)
d3497138f   Albert Aribaud   mvsata_ide: adjus...
147
  	status = mvsata_ide_initialize_port(
39419ce58   Albert Aribaud   ide: add mvsata_i...
148
149
  		(struct mvsata_port_registers *)
  		(CONFIG_SYS_ATA_BASE_ADDR + CONFIG_SYS_ATA_IDE1_OFFSET));
2cb4fade0   Simon Guinot   mvsata: fix ide_p...
150
151
  	if (status == MVSATA_STATUS_OK)
  		ret = MVSATA_STATUS_OK;
39419ce58   Albert Aribaud   ide: add mvsata_i...
152
  #endif
2cb4fade0   Simon Guinot   mvsata: fix ide_p...
153
154
  	/* Return success if at least one port initialization succeeded */
  	return ret;
39419ce58   Albert Aribaud   ide: add mvsata_i...
155
  }