Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
4d229fe2
Commit
4d229fe2
authored
Apr 21, 2004
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[libata] Promise driver split part 2: remove SX4 code from sata_promise
parent
2abc3c66
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
8 additions
and
1107 deletions
+8
-1107
drivers/scsi/sata_promise.c
drivers/scsi/sata_promise.c
+8
-1107
No files found.
drivers/scsi/sata_promise.c
View file @
4d229fe2
...
...
@@ -39,10 +39,7 @@
enum
{
PDC_PRD_TBL
=
0x44
,
/* Direct command DMA table addr */
PDC_PKT_SUBMIT
=
0x40
,
/* Command packet pointer addr */
PDC_HDMA_PKT_SUBMIT
=
0x100
,
/* Host DMA packet pointer addr */
PDC_INT_SEQMASK
=
0x40
,
/* Mask of asserted SEQ INTs */
PDC_TBG_MODE
=
0x41
,
/* TBG mode */
PDC_FLASH_CTL
=
0x44
,
/* Flash control register */
...
...
@@ -51,141 +48,38 @@ enum {
PDC_CTLSTAT
=
0x60
,
/* IDE control and status (per port) */
PDC_SATA_PLUG_CSR
=
0x6C
,
/* SATA Plug control/status reg */
PDC_SLEW_CTL
=
0x470
,
/* slew rate control reg */
PDC_HDMA_CTLSTAT
=
0x12C
,
/* Host DMA control / status */
PDC_20621_SEQCTL
=
0x400
,
PDC_20621_SEQMASK
=
0x480
,
PDC_20621_GENERAL_CTL
=
0x484
,
PDC_20621_PAGE_SIZE
=
(
32
*
1024
),
/* chosen, not constant, values; we design our own DIMM mem map */
PDC_20621_DIMM_WINDOW
=
0x0C
,
/* page# for 32K DIMM window */
PDC_20621_DIMM_BASE
=
0x00200000
,
PDC_20621_DIMM_DATA
=
(
64
*
1024
),
PDC_DIMM_DATA_STEP
=
(
256
*
1024
),
PDC_DIMM_WINDOW_STEP
=
(
8
*
1024
),
PDC_DIMM_HOST_PRD
=
(
6
*
1024
),
PDC_DIMM_HOST_PKT
=
(
128
*
0
),
PDC_DIMM_HPKT_PRD
=
(
128
*
1
),
PDC_DIMM_ATA_PKT
=
(
128
*
2
),
PDC_DIMM_APKT_PRD
=
(
128
*
3
),
PDC_DIMM_HEADER_SZ
=
PDC_DIMM_APKT_PRD
+
128
,
PDC_PAGE_WINDOW
=
0x40
,
PDC_PAGE_DATA
=
PDC_PAGE_WINDOW
+
(
PDC_20621_DIMM_DATA
/
PDC_20621_PAGE_SIZE
),
PDC_PAGE_SET
=
PDC_DIMM_DATA_STEP
/
PDC_20621_PAGE_SIZE
,
PDC_CHIP0_OFS
=
0xC0000
,
/* offset of chip #0 */
PDC_20621_ERR_MASK
=
(
1
<<
19
)
|
(
1
<<
20
)
|
(
1
<<
21
)
|
(
1
<<
22
)
|
(
1
<<
23
),
PDC_ERR_MASK
=
(
1
<<
19
)
|
(
1
<<
20
)
|
(
1
<<
21
)
|
(
1
<<
22
)
|
(
1
<<
8
)
|
(
1
<<
9
)
|
(
1
<<
10
),
board_2037x
=
0
,
/* FastTrak S150 TX2plus */
board_20319
=
1
,
/* FastTrak S150 TX4 */
board_20621
=
2
,
/* FastTrak S150 SX4 */
PDC_HAS_PATA
=
(
1
<<
1
),
/* PDC20375 has PATA */
PDC_FLAG_20621
=
(
1
<<
30
),
/* we have a 20621 */
PDC_RESET
=
(
1
<<
11
),
/* HDMA reset */
PDC_MAX_HDMA
=
32
,
PDC_HDMA_Q_MASK
=
(
PDC_MAX_HDMA
-
1
),
PDC_DIMM0_SPD_DEV_ADDRESS
=
0x50
,
PDC_DIMM1_SPD_DEV_ADDRESS
=
0x51
,
PDC_MAX_DIMM_MODULE
=
0x02
,
PDC_I2C_CONTROL_OFFSET
=
0x48
,
PDC_I2C_ADDR_DATA_OFFSET
=
0x4C
,
PDC_DIMM0_CONTROL_OFFSET
=
0x80
,
PDC_DIMM1_CONTROL_OFFSET
=
0x84
,
PDC_SDRAM_CONTROL_OFFSET
=
0x88
,
PDC_I2C_WRITE
=
0x00000000
,
PDC_I2C_READ
=
0x00000040
,
PDC_I2C_START
=
0x00000080
,
PDC_I2C_MASK_INT
=
0x00000020
,
PDC_I2C_COMPLETE
=
0x00010000
,
PDC_I2C_NO_ACK
=
0x00100000
,
PDC_DIMM_SPD_SUBADDRESS_START
=
0x00
,
PDC_DIMM_SPD_SUBADDRESS_END
=
0x7F
,
PDC_DIMM_SPD_ROW_NUM
=
3
,
PDC_DIMM_SPD_COLUMN_NUM
=
4
,
PDC_DIMM_SPD_MODULE_ROW
=
5
,
PDC_DIMM_SPD_TYPE
=
11
,
PDC_DIMM_SPD_FRESH_RATE
=
12
,
PDC_DIMM_SPD_BANK_NUM
=
17
,
PDC_DIMM_SPD_CAS_LATENCY
=
18
,
PDC_DIMM_SPD_ATTRIBUTE
=
21
,
PDC_DIMM_SPD_ROW_PRE_CHARGE
=
27
,
PDC_DIMM_SPD_ROW_ACTIVE_DELAY
=
28
,
PDC_DIMM_SPD_RAS_CAS_DELAY
=
29
,
PDC_DIMM_SPD_ACTIVE_PRECHARGE
=
30
,
PDC_DIMM_SPD_SYSTEM_FREQ
=
126
,
PDC_CTL_STATUS
=
0x08
,
PDC_DIMM_WINDOW_CTLR
=
0x0C
,
PDC_TIME_CONTROL
=
0x3C
,
PDC_TIME_PERIOD
=
0x40
,
PDC_TIME_COUNTER
=
0x44
,
PDC_GENERAL_CTLR
=
0x484
,
PCI_PLL_INIT
=
0x8A531824
,
PCI_X_TCOUNT
=
0xEE1E5CFF
};
struct
pdc_port_priv
{
u8
dimm_buf
[(
ATA_PRD_SZ
*
ATA_MAX_PRD
)
+
512
];
u8
*
pkt
;
dma_addr_t
pkt_dma
;
};
struct
pdc_host_priv
{
void
*
dimm_mmio
;
unsigned
int
doing_hdma
;
unsigned
int
hdma_prod
;
unsigned
int
hdma_cons
;
struct
{
struct
ata_queued_cmd
*
qc
;
unsigned
int
seq
;
unsigned
long
pkt_ofs
;
}
hdma
[
32
];
};
static
u32
pdc_sata_scr_read
(
struct
ata_port
*
ap
,
unsigned
int
sc_reg
);
static
void
pdc_sata_scr_write
(
struct
ata_port
*
ap
,
unsigned
int
sc_reg
,
u32
val
);
static
int
pdc_sata_init_one
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
);
static
void
pdc_dma_start
(
struct
ata_queued_cmd
*
qc
);
static
void
pdc20621_dma_start
(
struct
ata_queued_cmd
*
qc
);
static
irqreturn_t
pdc_interrupt
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
);
static
irqreturn_t
pdc20621_interrupt
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
);
static
void
pdc_eng_timeout
(
struct
ata_port
*
ap
);
static
void
pdc_20621_phy_reset
(
struct
ata_port
*
ap
);
static
int
pdc_port_start
(
struct
ata_port
*
ap
);
static
void
pdc_port_stop
(
struct
ata_port
*
ap
);
static
void
pdc_phy_reset
(
struct
ata_port
*
ap
);
static
void
pdc_fill_sg
(
struct
ata_queued_cmd
*
qc
);
static
void
pdc20621_fill_sg
(
struct
ata_queued_cmd
*
qc
);
static
void
pdc_tf_load_mmio
(
struct
ata_port
*
ap
,
struct
ata_taskfile
*
tf
);
static
void
pdc_exec_command_mmio
(
struct
ata_port
*
ap
,
struct
ata_taskfile
*
tf
);
static
void
pdc20621_host_stop
(
struct
ata_host_set
*
host_set
);
static
inline
void
pdc_dma_complete
(
struct
ata_port
*
ap
,
struct
ata_queued_cmd
*
qc
,
int
have_err
);
static
unsigned
int
pdc20621_dimm_init
(
struct
ata_probe_ent
*
pe
);
static
int
pdc20621_detect_dimm
(
struct
ata_probe_ent
*
pe
);
static
unsigned
int
pdc20621_i2c_read
(
struct
ata_probe_ent
*
pe
,
u32
device
,
u32
subaddr
,
u32
*
pdata
);
static
int
pdc20621_prog_dimm0
(
struct
ata_probe_ent
*
pe
);
static
unsigned
int
pdc20621_prog_dimm_global
(
struct
ata_probe_ent
*
pe
);
#ifdef ATA_VERBOSE_DEBUG
static
void
pdc20621_get_from_dimm
(
struct
ata_probe_ent
*
pe
,
void
*
psource
,
u32
offset
,
u32
size
);
#endif
static
void
pdc20621_put_to_dimm
(
struct
ata_probe_ent
*
pe
,
void
*
psource
,
u32
offset
,
u32
size
);
static
Scsi_Host_Template
pdc_sata_sht
=
{
.
module
=
THIS_MODULE
,
...
...
@@ -222,22 +116,6 @@ static struct ata_port_operations pdc_sata_ops = {
.
port_stop
=
pdc_port_stop
,
};
static
struct
ata_port_operations
pdc_20621_ops
=
{
.
port_disable
=
ata_port_disable
,
.
tf_load
=
pdc_tf_load_mmio
,
.
tf_read
=
ata_tf_read_mmio
,
.
check_status
=
ata_check_status_mmio
,
.
exec_command
=
pdc_exec_command_mmio
,
.
phy_reset
=
pdc_20621_phy_reset
,
.
bmdma_start
=
pdc20621_dma_start
,
.
fill_sg
=
pdc20621_fill_sg
,
.
eng_timeout
=
pdc_eng_timeout
,
.
irq_handler
=
pdc20621_interrupt
,
.
port_start
=
pdc_port_start
,
.
port_stop
=
pdc_port_stop
,
.
host_stop
=
pdc20621_host_stop
,
};
static
struct
ata_port_info
pdc_port_info
[]
=
{
/* board_2037x */
{
...
...
@@ -258,18 +136,6 @@ static struct ata_port_info pdc_port_info[] = {
.
udma_mask
=
0x7f
,
/* udma0-6 ; FIXME */
.
port_ops
=
&
pdc_sata_ops
,
},
/* board_20621 */
{
.
sht
=
&
pdc_sata_sht
,
.
host_flags
=
ATA_FLAG_SATA
|
ATA_FLAG_NO_LEGACY
|
ATA_FLAG_SRST
|
ATA_FLAG_MMIO
|
PDC_FLAG_20621
,
.
pio_mask
=
0x03
,
/* pio3-4 */
.
udma_mask
=
0x7f
,
/* udma0-6 ; FIXME */
.
port_ops
=
&
pdc_20621_ops
,
},
};
static
struct
pci_device_id
pdc_sata_pci_tbl
[]
=
{
...
...
@@ -285,8 +151,6 @@ static struct pci_device_id pdc_sata_pci_tbl[] = {
board_20319
},
{
PCI_VENDOR_ID_PROMISE
,
0x3319
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
board_20319
},
{
PCI_VENDOR_ID_PROMISE
,
0x6622
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
board_20621
},
{
}
/* terminate list */
};
...
...
@@ -299,15 +163,6 @@ static struct pci_driver pdc_sata_pci_driver = {
};
static
void
pdc20621_host_stop
(
struct
ata_host_set
*
host_set
)
{
struct
pdc_host_priv
*
hpriv
=
host_set
->
private_data
;
void
*
dimm_mmio
=
hpriv
->
dimm_mmio
;
iounmap
(
dimm_mmio
);
kfree
(
hpriv
);
}
static
int
pdc_port_start
(
struct
ata_port
*
ap
)
{
struct
pci_dev
*
pdev
=
ap
->
host_set
->
pdev
;
...
...
@@ -355,14 +210,6 @@ static void pdc_port_stop(struct ata_port *ap)
}
static
void
pdc_20621_phy_reset
(
struct
ata_port
*
ap
)
{
VPRINTK
(
"ENTER
\n
"
);
ap
->
cbl
=
ATA_CBL_SATA
;
ata_port_probe
(
ap
);
ata_bus_reset
(
ap
);
}
static
void
pdc_reset_port
(
struct
ata_port
*
ap
)
{
void
*
mmio
=
(
void
*
)
ap
->
ioaddr
.
cmd_addr
+
PDC_CTLSTAT
;
...
...
@@ -531,463 +378,6 @@ static inline unsigned int pdc_prep_lba48(struct ata_taskfile *tf, u8 *buf, unsi
return
i
;
}
static
inline
void
pdc20621_ata_sg
(
struct
ata_taskfile
*
tf
,
u8
*
buf
,
unsigned
int
portno
,
unsigned
int
total_len
)
{
u32
addr
;
unsigned
int
dw
=
PDC_DIMM_APKT_PRD
>>
2
;
u32
*
buf32
=
(
u32
*
)
buf
;
/* output ATA packet S/G table */
addr
=
PDC_20621_DIMM_BASE
+
PDC_20621_DIMM_DATA
+
(
PDC_DIMM_DATA_STEP
*
portno
);
VPRINTK
(
"ATA sg addr 0x%x, %d
\n
"
,
addr
,
addr
);
buf32
[
dw
]
=
cpu_to_le32
(
addr
);
buf32
[
dw
+
1
]
=
cpu_to_le32
(
total_len
|
ATA_PRD_EOT
);
VPRINTK
(
"ATA PSG @ %x == (0x%x, 0x%x)
\n
"
,
PDC_20621_DIMM_BASE
+
(
PDC_DIMM_WINDOW_STEP
*
portno
)
+
PDC_DIMM_APKT_PRD
,
buf32
[
dw
],
buf32
[
dw
+
1
]);
}
static
inline
void
pdc20621_host_sg
(
struct
ata_taskfile
*
tf
,
u8
*
buf
,
unsigned
int
portno
,
unsigned
int
total_len
)
{
u32
addr
;
unsigned
int
dw
=
PDC_DIMM_HPKT_PRD
>>
2
;
u32
*
buf32
=
(
u32
*
)
buf
;
/* output Host DMA packet S/G table */
addr
=
PDC_20621_DIMM_BASE
+
PDC_20621_DIMM_DATA
+
(
PDC_DIMM_DATA_STEP
*
portno
);
buf32
[
dw
]
=
cpu_to_le32
(
addr
);
buf32
[
dw
+
1
]
=
cpu_to_le32
(
total_len
|
ATA_PRD_EOT
);
VPRINTK
(
"HOST PSG @ %x == (0x%x, 0x%x)
\n
"
,
PDC_20621_DIMM_BASE
+
(
PDC_DIMM_WINDOW_STEP
*
portno
)
+
PDC_DIMM_HPKT_PRD
,
buf32
[
dw
],
buf32
[
dw
+
1
]);
}
static
inline
unsigned
int
pdc20621_ata_pkt
(
struct
ata_taskfile
*
tf
,
unsigned
int
devno
,
u8
*
buf
,
unsigned
int
portno
)
{
unsigned
int
i
,
dw
;
u32
*
buf32
=
(
u32
*
)
buf
;
u8
dev_reg
;
unsigned
int
dimm_sg
=
PDC_20621_DIMM_BASE
+
(
PDC_DIMM_WINDOW_STEP
*
portno
)
+
PDC_DIMM_APKT_PRD
;
VPRINTK
(
"ENTER, dimm_sg == 0x%x, %d
\n
"
,
dimm_sg
,
dimm_sg
);
i
=
PDC_DIMM_ATA_PKT
;
/*
* Set up ATA packet
*/
if
((
tf
->
protocol
==
ATA_PROT_DMA
)
&&
(
!
(
tf
->
flags
&
ATA_TFLAG_WRITE
)))
buf
[
i
++
]
=
PDC_PKT_READ
;
else
if
(
tf
->
protocol
==
ATA_PROT_NODATA
)
buf
[
i
++
]
=
PDC_PKT_NODATA
;
else
buf
[
i
++
]
=
0
;
buf
[
i
++
]
=
0
;
/* reserved */
buf
[
i
++
]
=
portno
+
1
;
/* seq. id */
buf
[
i
++
]
=
0xff
;
/* delay seq. id */
/* dimm dma S/G, and next-pkt */
dw
=
i
>>
2
;
buf32
[
dw
]
=
cpu_to_le32
(
dimm_sg
);
buf32
[
dw
+
1
]
=
0
;
i
+=
8
;
if
(
devno
==
0
)
dev_reg
=
ATA_DEVICE_OBS
;
else
dev_reg
=
ATA_DEVICE_OBS
|
ATA_DEV1
;
/* select device */
buf
[
i
++
]
=
(
1
<<
5
)
|
PDC_PKT_CLEAR_BSY
|
ATA_REG_DEVICE
;
buf
[
i
++
]
=
dev_reg
;
/* device control register */
buf
[
i
++
]
=
(
1
<<
5
)
|
PDC_REG_DEVCTL
;
buf
[
i
++
]
=
tf
->
ctl
;
return
i
;
}
static
inline
void
pdc20621_host_pkt
(
struct
ata_taskfile
*
tf
,
u8
*
buf
,
unsigned
int
portno
)
{
unsigned
int
dw
;
u32
tmp
,
*
buf32
=
(
u32
*
)
buf
;
unsigned
int
host_sg
=
PDC_20621_DIMM_BASE
+
(
PDC_DIMM_WINDOW_STEP
*
portno
)
+
PDC_DIMM_HOST_PRD
;
unsigned
int
dimm_sg
=
PDC_20621_DIMM_BASE
+
(
PDC_DIMM_WINDOW_STEP
*
portno
)
+
PDC_DIMM_HPKT_PRD
;
VPRINTK
(
"ENTER, dimm_sg == 0x%x, %d
\n
"
,
dimm_sg
,
dimm_sg
);
VPRINTK
(
"host_sg == 0x%x, %d
\n
"
,
host_sg
,
host_sg
);
dw
=
PDC_DIMM_HOST_PKT
>>
2
;
/*
* Set up Host DMA packet
*/
if
((
tf
->
protocol
==
ATA_PROT_DMA
)
&&
(
!
(
tf
->
flags
&
ATA_TFLAG_WRITE
)))
tmp
=
PDC_PKT_READ
;
else
tmp
=
0
;
tmp
|=
((
portno
+
1
+
4
)
<<
16
);
/* seq. id */
tmp
|=
(
0xff
<<
24
);
/* delay seq. id */
buf32
[
dw
+
0
]
=
cpu_to_le32
(
tmp
);
buf32
[
dw
+
1
]
=
cpu_to_le32
(
host_sg
);
buf32
[
dw
+
2
]
=
cpu_to_le32
(
dimm_sg
);
buf32
[
dw
+
3
]
=
0
;
VPRINTK
(
"HOST PKT @ %x == (0x%x 0x%x 0x%x 0x%x)
\n
"
,
PDC_20621_DIMM_BASE
+
(
PDC_DIMM_WINDOW_STEP
*
portno
)
+
PDC_DIMM_HOST_PKT
,
buf32
[
dw
+
0
],
buf32
[
dw
+
1
],
buf32
[
dw
+
2
],
buf32
[
dw
+
3
]);
}
static
void
pdc20621_fill_sg
(
struct
ata_queued_cmd
*
qc
)
{
struct
scatterlist
*
sg
=
qc
->
sg
;
struct
ata_port
*
ap
=
qc
->
ap
;
struct
pdc_port_priv
*
pp
=
ap
->
private_data
;
void
*
mmio
=
ap
->
host_set
->
mmio_base
;
struct
pdc_host_priv
*
hpriv
=
ap
->
host_set
->
private_data
;
void
*
dimm_mmio
=
hpriv
->
dimm_mmio
;
unsigned
int
portno
=
ap
->
port_no
;
unsigned
int
i
,
last
,
idx
,
total_len
=
0
,
sgt_len
;
u32
*
buf
=
(
u32
*
)
&
pp
->
dimm_buf
[
PDC_DIMM_HEADER_SZ
];
VPRINTK
(
"ata%u: ENTER
\n
"
,
ap
->
id
);
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
/*
* Build S/G table
*/
last
=
qc
->
n_elem
;
idx
=
0
;
for
(
i
=
0
;
i
<
last
;
i
++
)
{
buf
[
idx
++
]
=
cpu_to_le32
(
sg_dma_address
(
&
sg
[
i
]));
buf
[
idx
++
]
=
cpu_to_le32
(
sg_dma_len
(
&
sg
[
i
]));
total_len
+=
sg
[
i
].
length
;
}
buf
[
idx
-
1
]
|=
cpu_to_le32
(
ATA_PRD_EOT
);
sgt_len
=
idx
*
4
;
/*
* Build ATA, host DMA packets
*/
pdc20621_host_sg
(
&
qc
->
tf
,
&
pp
->
dimm_buf
[
0
],
portno
,
total_len
);
pdc20621_host_pkt
(
&
qc
->
tf
,
&
pp
->
dimm_buf
[
0
],
portno
);
pdc20621_ata_sg
(
&
qc
->
tf
,
&
pp
->
dimm_buf
[
0
],
portno
,
total_len
);
i
=
pdc20621_ata_pkt
(
&
qc
->
tf
,
qc
->
dev
->
devno
,
&
pp
->
dimm_buf
[
0
],
portno
);
if
(
qc
->
tf
.
flags
&
ATA_TFLAG_LBA48
)
i
=
pdc_prep_lba48
(
&
qc
->
tf
,
&
pp
->
dimm_buf
[
0
],
i
);
else
i
=
pdc_prep_lba28
(
&
qc
->
tf
,
&
pp
->
dimm_buf
[
0
],
i
);
pdc_pkt_footer
(
&
qc
->
tf
,
&
pp
->
dimm_buf
[
0
],
i
);
/* copy three S/G tables and two packets to DIMM MMIO window */
memcpy_toio
(
dimm_mmio
+
(
portno
*
PDC_DIMM_WINDOW_STEP
),
&
pp
->
dimm_buf
,
PDC_DIMM_HEADER_SZ
);
memcpy_toio
(
dimm_mmio
+
(
portno
*
PDC_DIMM_WINDOW_STEP
)
+
PDC_DIMM_HOST_PRD
,
&
pp
->
dimm_buf
[
PDC_DIMM_HEADER_SZ
],
sgt_len
);
/* force host FIFO dump */
writel
(
0x00000001
,
mmio
+
PDC_20621_GENERAL_CTL
);
readl
(
dimm_mmio
);
/* MMIO PCI posting flush */
VPRINTK
(
"ata pkt buf ofs %u, prd size %u, mmio copied
\n
"
,
i
,
sgt_len
);
}
static
void
__pdc20621_push_hdma
(
struct
ata_queued_cmd
*
qc
,
unsigned
int
seq
,
u32
pkt_ofs
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
struct
ata_host_set
*
host_set
=
ap
->
host_set
;
void
*
mmio
=
host_set
->
mmio_base
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
writel
(
0x00000001
,
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
readl
(
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
/* flush */
writel
(
pkt_ofs
,
mmio
+
PDC_HDMA_PKT_SUBMIT
);
readl
(
mmio
+
PDC_HDMA_PKT_SUBMIT
);
/* flush */
}
static
void
pdc20621_push_hdma
(
struct
ata_queued_cmd
*
qc
,
unsigned
int
seq
,
u32
pkt_ofs
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
struct
pdc_host_priv
*
pp
=
ap
->
host_set
->
private_data
;
unsigned
int
idx
=
pp
->
hdma_prod
&
PDC_HDMA_Q_MASK
;
if
(
!
pp
->
doing_hdma
)
{
__pdc20621_push_hdma
(
qc
,
seq
,
pkt_ofs
);
pp
->
doing_hdma
=
1
;
return
;
}
pp
->
hdma
[
idx
].
qc
=
qc
;
pp
->
hdma
[
idx
].
seq
=
seq
;
pp
->
hdma
[
idx
].
pkt_ofs
=
pkt_ofs
;
pp
->
hdma_prod
++
;
}
static
void
pdc20621_pop_hdma
(
struct
ata_queued_cmd
*
qc
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
struct
pdc_host_priv
*
pp
=
ap
->
host_set
->
private_data
;
unsigned
int
idx
=
pp
->
hdma_cons
&
PDC_HDMA_Q_MASK
;
/* if nothing on queue, we're done */
if
(
pp
->
hdma_prod
==
pp
->
hdma_cons
)
{
pp
->
doing_hdma
=
0
;
return
;
}
__pdc20621_push_hdma
(
pp
->
hdma
[
idx
].
qc
,
pp
->
hdma
[
idx
].
seq
,
pp
->
hdma
[
idx
].
pkt_ofs
);
pp
->
hdma_cons
++
;
}
#ifdef ATA_VERBOSE_DEBUG
static
void
pdc20621_dump_hdma
(
struct
ata_queued_cmd
*
qc
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
unsigned
int
port_no
=
ap
->
port_no
;
struct
pdc_host_priv
*
hpriv
=
ap
->
host_set
->
private_data
;
void
*
dimm_mmio
=
hpriv
->
dimm_mmio
;
dimm_mmio
+=
(
port_no
*
PDC_DIMM_WINDOW_STEP
);
dimm_mmio
+=
PDC_DIMM_HOST_PKT
;
printk
(
KERN_ERR
"HDMA[0] == 0x%08X
\n
"
,
readl
(
dimm_mmio
));
printk
(
KERN_ERR
"HDMA[1] == 0x%08X
\n
"
,
readl
(
dimm_mmio
+
4
));
printk
(
KERN_ERR
"HDMA[2] == 0x%08X
\n
"
,
readl
(
dimm_mmio
+
8
));
printk
(
KERN_ERR
"HDMA[3] == 0x%08X
\n
"
,
readl
(
dimm_mmio
+
12
));
}
#else
static
inline
void
pdc20621_dump_hdma
(
struct
ata_queued_cmd
*
qc
)
{
}
#endif
/* ATA_VERBOSE_DEBUG */
static
void
pdc20621_dma_start
(
struct
ata_queued_cmd
*
qc
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
struct
ata_host_set
*
host_set
=
ap
->
host_set
;
unsigned
int
port_no
=
ap
->
port_no
;
void
*
mmio
=
host_set
->
mmio_base
;
unsigned
int
rw
=
(
qc
->
tf
.
flags
&
ATA_TFLAG_WRITE
);
u8
seq
=
(
u8
)
(
port_no
+
1
);
unsigned
int
doing_hdma
=
0
,
port_ofs
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
VPRINTK
(
"ata%u: ENTER
\n
"
,
ap
->
id
);
port_ofs
=
PDC_20621_DIMM_BASE
+
(
PDC_DIMM_WINDOW_STEP
*
port_no
);
/* if writing, we (1) DMA to DIMM, then (2) do ATA command */
if
(
rw
)
{
doing_hdma
=
1
;
seq
+=
4
;
}
wmb
();
/* flush PRD, pkt writes */
if
(
doing_hdma
)
{
pdc20621_dump_hdma
(
qc
);
pdc20621_push_hdma
(
qc
,
seq
,
port_ofs
+
PDC_DIMM_HOST_PKT
);
VPRINTK
(
"queued ofs 0x%x (%u), seq %u
\n
"
,
port_ofs
+
PDC_DIMM_HOST_PKT
,
port_ofs
+
PDC_DIMM_HOST_PKT
,
seq
);
}
else
{
writel
(
0x00000001
,
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
readl
(
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
/* flush */
writel
(
port_ofs
+
PDC_DIMM_ATA_PKT
,
(
void
*
)
ap
->
ioaddr
.
cmd_addr
+
PDC_PKT_SUBMIT
);
readl
((
void
*
)
ap
->
ioaddr
.
cmd_addr
+
PDC_PKT_SUBMIT
);
VPRINTK
(
"submitted ofs 0x%x (%u), seq %u
\n
"
,
port_ofs
+
PDC_DIMM_ATA_PKT
,
port_ofs
+
PDC_DIMM_ATA_PKT
,
seq
);
}
}
static
inline
unsigned
int
pdc20621_host_intr
(
struct
ata_port
*
ap
,
struct
ata_queued_cmd
*
qc
,
unsigned
int
doing_hdma
,
void
*
mmio
)
{
unsigned
int
port_no
=
ap
->
port_no
;
unsigned
int
port_ofs
=
PDC_20621_DIMM_BASE
+
(
PDC_DIMM_WINDOW_STEP
*
port_no
);
u8
status
;
unsigned
int
handled
=
0
;
VPRINTK
(
"ENTER
\n
"
);
if
((
qc
->
tf
.
protocol
==
ATA_PROT_DMA
)
&&
/* read */
(
!
(
qc
->
tf
.
flags
&
ATA_TFLAG_WRITE
)))
{
/* step two - DMA from DIMM to host */
if
(
doing_hdma
)
{
VPRINTK
(
"ata%u: read hdma, 0x%x 0x%x
\n
"
,
ap
->
id
,
readl
(
mmio
+
0x104
),
readl
(
mmio
+
PDC_HDMA_CTLSTAT
));
pdc_dma_complete
(
ap
,
qc
,
0
);
pdc20621_pop_hdma
(
qc
);
}
/* step one - exec ATA command */
else
{
u8
seq
=
(
u8
)
(
port_no
+
1
+
4
);
VPRINTK
(
"ata%u: read ata, 0x%x 0x%x
\n
"
,
ap
->
id
,
readl
(
mmio
+
0x104
),
readl
(
mmio
+
PDC_HDMA_CTLSTAT
));
/* submit hdma pkt */
pdc20621_dump_hdma
(
qc
);
pdc20621_push_hdma
(
qc
,
seq
,
port_ofs
+
PDC_DIMM_HOST_PKT
);
}
handled
=
1
;
}
else
if
(
qc
->
tf
.
protocol
==
ATA_PROT_DMA
)
{
/* write */
/* step one - DMA from host to DIMM */
if
(
doing_hdma
)
{
u8
seq
=
(
u8
)
(
port_no
+
1
);
VPRINTK
(
"ata%u: write hdma, 0x%x 0x%x
\n
"
,
ap
->
id
,
readl
(
mmio
+
0x104
),
readl
(
mmio
+
PDC_HDMA_CTLSTAT
));
/* submit ata pkt */
writel
(
0x00000001
,
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
readl
(
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
writel
(
port_ofs
+
PDC_DIMM_ATA_PKT
,
(
void
*
)
ap
->
ioaddr
.
cmd_addr
+
PDC_PKT_SUBMIT
);
readl
((
void
*
)
ap
->
ioaddr
.
cmd_addr
+
PDC_PKT_SUBMIT
);
}
/* step two - execute ATA command */
else
{
VPRINTK
(
"ata%u: write ata, 0x%x 0x%x
\n
"
,
ap
->
id
,
readl
(
mmio
+
0x104
),
readl
(
mmio
+
PDC_HDMA_CTLSTAT
));
pdc_dma_complete
(
ap
,
qc
,
0
);
pdc20621_pop_hdma
(
qc
);
}
handled
=
1
;
/* command completion, but no data xfer */
}
else
if
(
qc
->
tf
.
protocol
==
ATA_PROT_NODATA
)
{
status
=
ata_busy_wait
(
ap
,
ATA_BUSY
|
ATA_DRQ
,
1000
);
DPRINTK
(
"BUS_NODATA (drv_stat 0x%X)
\n
"
,
status
);
ata_qc_complete
(
qc
,
status
,
0
);
handled
=
1
;
}
else
{
ap
->
stats
.
idle_irq
++
;
}
return
handled
;
}
static
irqreturn_t
pdc20621_interrupt
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
)
{
struct
ata_host_set
*
host_set
=
dev_instance
;
struct
ata_port
*
ap
;
u32
mask
=
0
;
unsigned
int
i
,
tmp
,
port_no
;
unsigned
int
handled
=
0
;
void
*
mmio_base
;
VPRINTK
(
"ENTER
\n
"
);
if
(
!
host_set
||
!
host_set
->
mmio_base
)
{
VPRINTK
(
"QUICK EXIT
\n
"
);
return
IRQ_NONE
;
}
mmio_base
=
host_set
->
mmio_base
;
/* reading should also clear interrupts */
mmio_base
+=
PDC_CHIP0_OFS
;
mask
=
readl
(
mmio_base
+
PDC_20621_SEQMASK
);
VPRINTK
(
"mask == 0x%x
\n
"
,
mask
);
if
(
mask
==
0xffffffff
)
{
VPRINTK
(
"QUICK EXIT 2
\n
"
);
return
IRQ_NONE
;
}
mask
&=
0xffff
;
/* only 16 tags possible */
if
(
!
mask
)
{
VPRINTK
(
"QUICK EXIT 3
\n
"
);
return
IRQ_NONE
;
}
spin_lock
(
&
host_set
->
lock
);
for
(
i
=
1
;
i
<
9
;
i
++
)
{
port_no
=
i
-
1
;
if
(
port_no
>
3
)
port_no
-=
4
;
if
(
port_no
>=
host_set
->
n_ports
)
ap
=
NULL
;
else
ap
=
host_set
->
ports
[
port_no
];
tmp
=
mask
&
(
1
<<
i
);
VPRINTK
(
"seq %u, port_no %u, ap %p, tmp %x
\n
"
,
i
,
port_no
,
ap
,
tmp
);
if
(
tmp
&&
ap
&&
(
!
(
ap
->
flags
&
ATA_FLAG_PORT_DISABLED
)))
{
struct
ata_queued_cmd
*
qc
;
qc
=
ata_qc_from_tag
(
ap
,
ap
->
active_tag
);
if
(
qc
&&
((
qc
->
flags
&
ATA_QCFLAG_POLL
)
==
0
))
handled
+=
pdc20621_host_intr
(
ap
,
qc
,
(
i
>
4
),
mmio_base
);
}
}
spin_unlock
(
&
host_set
->
lock
);
VPRINTK
(
"mask == 0x%x
\n
"
,
mask
);
VPRINTK
(
"EXIT
\n
"
);
return
IRQ_RETVAL
(
handled
);
}
static
void
pdc_fill_sg
(
struct
ata_queued_cmd
*
qc
)
{
struct
pdc_port_priv
*
pp
=
qc
->
ap
->
private_data
;
...
...
@@ -1210,456 +600,11 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
}
#ifdef ATA_VERBOSE_DEBUG
static
void
pdc20621_get_from_dimm
(
struct
ata_probe_ent
*
pe
,
void
*
psource
,
u32
offset
,
u32
size
)
{
u32
window_size
;
u16
idx
;
u8
page_mask
;
long
dist
;
void
*
mmio
=
pe
->
mmio_base
;
struct
pdc_host_priv
*
hpriv
=
pe
->
private_data
;
void
*
dimm_mmio
=
hpriv
->
dimm_mmio
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
page_mask
=
0x00
;
window_size
=
0x2000
*
4
;
/* 32K byte uchar size */
idx
=
(
u16
)
(
offset
/
window_size
);
writel
(
0x01
,
mmio
+
PDC_GENERAL_CTLR
);
readl
(
mmio
+
PDC_GENERAL_CTLR
);
writel
(((
idx
)
<<
page_mask
),
mmio
+
PDC_DIMM_WINDOW_CTLR
);
readl
(
mmio
+
PDC_DIMM_WINDOW_CTLR
);
offset
-=
(
idx
*
window_size
);
idx
++
;
dist
=
((
long
)
(
window_size
-
(
offset
+
size
)))
>=
0
?
size
:
(
long
)
(
window_size
-
offset
);
memcpy_fromio
((
char
*
)
psource
,
(
char
*
)
(
dimm_mmio
+
offset
/
4
),
dist
);
psource
+=
dist
;
size
-=
dist
;
for
(;
(
long
)
size
>=
(
long
)
window_size
;)
{
writel
(
0x01
,
mmio
+
PDC_GENERAL_CTLR
);
readl
(
mmio
+
PDC_GENERAL_CTLR
);
writel
(((
idx
)
<<
page_mask
),
mmio
+
PDC_DIMM_WINDOW_CTLR
);
readl
(
mmio
+
PDC_DIMM_WINDOW_CTLR
);
memcpy_fromio
((
char
*
)
psource
,
(
char
*
)
(
dimm_mmio
),
window_size
/
4
);
psource
+=
window_size
;
size
-=
window_size
;
idx
++
;
}
if
(
size
)
{
writel
(
0x01
,
mmio
+
PDC_GENERAL_CTLR
);
readl
(
mmio
+
PDC_GENERAL_CTLR
);
writel
(((
idx
)
<<
page_mask
),
mmio
+
PDC_DIMM_WINDOW_CTLR
);
readl
(
mmio
+
PDC_DIMM_WINDOW_CTLR
);
memcpy_fromio
((
char
*
)
psource
,
(
char
*
)
(
dimm_mmio
),
size
/
4
);
}
}
#endif
static
void
pdc20621_put_to_dimm
(
struct
ata_probe_ent
*
pe
,
void
*
psource
,
u32
offset
,
u32
size
)
{
u32
window_size
;
u16
idx
;
u8
page_mask
;
long
dist
;
void
*
mmio
=
pe
->
mmio_base
;
struct
pdc_host_priv
*
hpriv
=
pe
->
private_data
;
void
*
dimm_mmio
=
hpriv
->
dimm_mmio
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
page_mask
=
0x00
;
window_size
=
0x2000
*
4
;
/* 32K byte uchar size */
idx
=
(
u16
)
(
offset
/
window_size
);
writel
(((
idx
)
<<
page_mask
),
mmio
+
PDC_DIMM_WINDOW_CTLR
);
readl
(
mmio
+
PDC_DIMM_WINDOW_CTLR
);
offset
-=
(
idx
*
window_size
);
idx
++
;
dist
=
((
long
)
(
window_size
-
(
offset
+
size
)))
>=
0
?
size
:
(
long
)
(
window_size
-
offset
);
memcpy_toio
((
char
*
)
(
dimm_mmio
+
offset
/
4
),
(
char
*
)
psource
,
dist
);
writel
(
0x01
,
mmio
+
PDC_GENERAL_CTLR
);
readl
(
mmio
+
PDC_GENERAL_CTLR
);
psource
+=
dist
;
size
-=
dist
;
for
(;
(
long
)
size
>=
(
long
)
window_size
;)
{
writel
(((
idx
)
<<
page_mask
),
mmio
+
PDC_DIMM_WINDOW_CTLR
);
readl
(
mmio
+
PDC_DIMM_WINDOW_CTLR
);
memcpy_toio
((
char
*
)
(
dimm_mmio
),
(
char
*
)
psource
,
window_size
/
4
);
writel
(
0x01
,
mmio
+
PDC_GENERAL_CTLR
);
readl
(
mmio
+
PDC_GENERAL_CTLR
);
psource
+=
window_size
;
size
-=
window_size
;
idx
++
;
}
if
(
size
)
{
writel
(((
idx
)
<<
page_mask
),
mmio
+
PDC_DIMM_WINDOW_CTLR
);
readl
(
mmio
+
PDC_DIMM_WINDOW_CTLR
);
memcpy_toio
((
char
*
)
(
dimm_mmio
),
(
char
*
)
psource
,
size
/
4
);
writel
(
0x01
,
mmio
+
PDC_GENERAL_CTLR
);
readl
(
mmio
+
PDC_GENERAL_CTLR
);
}
}
static
unsigned
int
pdc20621_i2c_read
(
struct
ata_probe_ent
*
pe
,
u32
device
,
u32
subaddr
,
u32
*
pdata
)
{
void
*
mmio
=
pe
->
mmio_base
;
u32
i2creg
=
0
;
u32
status
;
u32
count
=
0
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
i2creg
|=
device
<<
24
;
i2creg
|=
subaddr
<<
16
;
/* Set the device and subaddress */
writel
(
i2creg
,
mmio
+
PDC_I2C_ADDR_DATA_OFFSET
);
readl
(
mmio
+
PDC_I2C_ADDR_DATA_OFFSET
);
/* Write Control to perform read operation, mask int */
writel
(
PDC_I2C_READ
|
PDC_I2C_START
|
PDC_I2C_MASK_INT
,
mmio
+
PDC_I2C_CONTROL_OFFSET
);
for
(
count
=
0
;
count
<=
1000
;
count
++
)
{
status
=
readl
(
mmio
+
PDC_I2C_CONTROL_OFFSET
);
if
(
status
&
PDC_I2C_COMPLETE
)
{
status
=
readl
(
mmio
+
PDC_I2C_ADDR_DATA_OFFSET
);
break
;
}
else
if
(
count
==
1000
)
return
0
;
}
*
pdata
=
(
status
>>
8
)
&
0x000000ff
;
return
1
;
}
static
int
pdc20621_detect_dimm
(
struct
ata_probe_ent
*
pe
)
{
u32
data
=
0
;
if
(
pdc20621_i2c_read
(
pe
,
PDC_DIMM0_SPD_DEV_ADDRESS
,
PDC_DIMM_SPD_SYSTEM_FREQ
,
&
data
))
{
if
(
data
==
100
)
return
100
;
}
else
return
0
;
if
(
pdc20621_i2c_read
(
pe
,
PDC_DIMM0_SPD_DEV_ADDRESS
,
9
,
&
data
))
{
if
(
data
<=
0x75
)
return
133
;
}
else
return
0
;
return
0
;
}
static
int
pdc20621_prog_dimm0
(
struct
ata_probe_ent
*
pe
)
{
u32
spd0
[
50
];
u32
data
=
0
;
int
size
,
i
;
u8
bdimmsize
;
void
*
mmio
=
pe
->
mmio_base
;
static
const
struct
{
unsigned
int
reg
;
unsigned
int
ofs
;
}
pdc_i2c_read_data
[]
=
{
{
PDC_DIMM_SPD_TYPE
,
11
},
{
PDC_DIMM_SPD_FRESH_RATE
,
12
},
{
PDC_DIMM_SPD_COLUMN_NUM
,
4
},
{
PDC_DIMM_SPD_ATTRIBUTE
,
21
},
{
PDC_DIMM_SPD_ROW_NUM
,
3
},
{
PDC_DIMM_SPD_BANK_NUM
,
17
},
{
PDC_DIMM_SPD_MODULE_ROW
,
5
},
{
PDC_DIMM_SPD_ROW_PRE_CHARGE
,
27
},
{
PDC_DIMM_SPD_ROW_ACTIVE_DELAY
,
28
},
{
PDC_DIMM_SPD_RAS_CAS_DELAY
,
29
},
{
PDC_DIMM_SPD_ACTIVE_PRECHARGE
,
30
},
{
PDC_DIMM_SPD_CAS_LATENCY
,
18
},
};
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
pdc_i2c_read_data
);
i
++
)
pdc20621_i2c_read
(
pe
,
PDC_DIMM0_SPD_DEV_ADDRESS
,
pdc_i2c_read_data
[
i
].
reg
,
&
spd0
[
pdc_i2c_read_data
[
i
].
ofs
]);
data
|=
(
spd0
[
4
]
-
8
)
|
((
spd0
[
21
]
!=
0
)
<<
3
)
|
((
spd0
[
3
]
-
11
)
<<
4
);
data
|=
((
spd0
[
17
]
/
4
)
<<
6
)
|
((
spd0
[
5
]
/
2
)
<<
7
)
|
((((
spd0
[
27
]
+
9
)
/
10
)
-
1
)
<<
8
)
;
data
|=
(((((
spd0
[
29
]
>
spd0
[
28
])
?
spd0
[
29
]
:
spd0
[
28
])
+
9
)
/
10
)
-
1
)
<<
10
;
data
|=
((
spd0
[
30
]
-
spd0
[
29
]
+
9
)
/
10
-
2
)
<<
12
;
if
(
spd0
[
18
]
&
0x08
)
data
|=
((
0x03
)
<<
14
);
else
if
(
spd0
[
18
]
&
0x04
)
data
|=
((
0x02
)
<<
14
);
else
if
(
spd0
[
18
]
&
0x01
)
data
|=
((
0x01
)
<<
14
);
else
data
|=
(
0
<<
14
);
/*
Calculate the size of bDIMMSize (power of 2) and
merge the DIMM size by program start/end address.
*/
bdimmsize
=
spd0
[
4
]
+
(
spd0
[
5
]
/
2
)
+
spd0
[
3
]
+
(
spd0
[
17
]
/
2
)
+
3
;
size
=
(
1
<<
bdimmsize
)
>>
20
;
/* size = xxx(MB) */
data
|=
(((
size
/
16
)
-
1
)
<<
16
);
data
|=
(
0
<<
23
);
data
|=
8
;
writel
(
data
,
mmio
+
PDC_DIMM0_CONTROL_OFFSET
);
readl
(
mmio
+
PDC_DIMM0_CONTROL_OFFSET
);
return
size
;
}
static
unsigned
int
pdc20621_prog_dimm_global
(
struct
ata_probe_ent
*
pe
)
{
u32
data
,
spd0
;
int
error
,
i
;
void
*
mmio
=
pe
->
mmio_base
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
/*
Set To Default : DIMM Module Global Control Register (0x022259F1)
DIMM Arbitration Disable (bit 20)
DIMM Data/Control Output Driving Selection (bit12 - bit15)
Refresh Enable (bit 17)
*/
data
=
0x022259F1
;
writel
(
data
,
mmio
+
PDC_SDRAM_CONTROL_OFFSET
);
readl
(
mmio
+
PDC_SDRAM_CONTROL_OFFSET
);
/* Turn on for ECC */
pdc20621_i2c_read
(
pe
,
PDC_DIMM0_SPD_DEV_ADDRESS
,
PDC_DIMM_SPD_TYPE
,
&
spd0
);
if
(
spd0
==
0x02
)
{
data
|=
(
0x01
<<
16
);
writel
(
data
,
mmio
+
PDC_SDRAM_CONTROL_OFFSET
);
readl
(
mmio
+
PDC_SDRAM_CONTROL_OFFSET
);
printk
(
KERN_ERR
"Local DIMM ECC Enabled
\n
"
);
}
/* DIMM Initialization Select/Enable (bit 18/19) */
data
&=
(
~
(
1
<<
18
));
data
|=
(
1
<<
19
);
writel
(
data
,
mmio
+
PDC_SDRAM_CONTROL_OFFSET
);
error
=
1
;
for
(
i
=
1
;
i
<=
10
;
i
++
)
{
/* polling ~5 secs */
data
=
readl
(
mmio
+
PDC_SDRAM_CONTROL_OFFSET
);
if
(
!
(
data
&
(
1
<<
19
)))
{
error
=
0
;
break
;
}
set_current_state
(
TASK_INTERRUPTIBLE
);
schedule_timeout
((
i
*
100
)
*
HZ
/
1000
);
}
return
error
;
}
static
unsigned
int
pdc20621_dimm_init
(
struct
ata_probe_ent
*
pe
)
{
int
speed
,
size
,
length
;
u32
addr
,
spd0
,
pci_status
;
u32
tmp
=
0
;
u32
time_period
=
0
;
u32
tcount
=
0
;
u32
ticks
=
0
;
u32
clock
=
0
;
u32
fparam
=
0
;
void
*
mmio
=
pe
->
mmio_base
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
/* Initialize PLL based upon PCI Bus Frequency */
/* Initialize Time Period Register */
writel
(
0xffffffff
,
mmio
+
PDC_TIME_PERIOD
);
time_period
=
readl
(
mmio
+
PDC_TIME_PERIOD
);
VPRINTK
(
"Time Period Register (0x40): 0x%x
\n
"
,
time_period
);
/* Enable timer */
writel
(
0x00001a0
,
mmio
+
PDC_TIME_CONTROL
);
readl
(
mmio
+
PDC_TIME_CONTROL
);
/* Wait 3 seconds */
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
3
*
HZ
);
/*
When timer is enabled, counter is decreased every internal
clock cycle.
*/
tcount
=
readl
(
mmio
+
PDC_TIME_COUNTER
);
VPRINTK
(
"Time Counter Register (0x44): 0x%x
\n
"
,
tcount
);
/*
If SX4 is on PCI-X bus, after 3 seconds, the timer counter
register should be >= (0xffffffff - 3x10^8).
*/
if
(
tcount
>=
PCI_X_TCOUNT
)
{
ticks
=
(
time_period
-
tcount
);
VPRINTK
(
"Num counters 0x%x (%d)
\n
"
,
ticks
,
ticks
);
clock
=
(
ticks
/
300000
);
VPRINTK
(
"10 * Internal clk = 0x%x (%d)
\n
"
,
clock
,
clock
);
clock
=
(
clock
*
33
);
VPRINTK
(
"10 * Internal clk * 33 = 0x%x (%d)
\n
"
,
clock
,
clock
);
/* PLL F Param (bit 22:16) */
fparam
=
(
1400000
/
clock
)
-
2
;
VPRINTK
(
"PLL F Param: 0x%x (%d)
\n
"
,
fparam
,
fparam
);
/* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */
pci_status
=
(
0x8a001824
|
(
fparam
<<
16
));
}
else
pci_status
=
PCI_PLL_INIT
;
/* Initialize PLL. */
VPRINTK
(
"pci_status: 0x%x
\n
"
,
pci_status
);
writel
(
pci_status
,
mmio
+
PDC_CTL_STATUS
);
readl
(
mmio
+
PDC_CTL_STATUS
);
/*
Read SPD of DIMM by I2C interface,
and program the DIMM Module Controller.
*/
if
(
!
(
speed
=
pdc20621_detect_dimm
(
pe
)))
{
printk
(
KERN_ERR
"Detect Local DIMM Fail
\n
"
);
return
1
;
/* DIMM error */
}
VPRINTK
(
"Local DIMM Speed = %d
\n
"
,
speed
);
/* Programming DIMM0 Module Control Register (index_CID0:80h) */
size
=
pdc20621_prog_dimm0
(
pe
);
VPRINTK
(
"Local DIMM Size = %dMB
\n
"
,
size
);
/* Programming DIMM Module Global Control Register (index_CID0:88h) */
if
(
pdc20621_prog_dimm_global
(
pe
))
{
printk
(
KERN_ERR
"Programming DIMM Module Global Control Register Fail
\n
"
);
return
1
;
}
#ifdef ATA_VERBOSE_DEBUG
{
u8
test_parttern1
[
40
]
=
{
0x55
,
0xAA
,
'P'
,
'r'
,
'o'
,
'm'
,
'i'
,
's'
,
'e'
,
' '
,
'N'
,
'o'
,
't'
,
' '
,
'Y'
,
'e'
,
't'
,
' '
,
'D'
,
'e'
,
'f'
,
'i'
,
'n'
,
'e'
,
'd'
,
' '
,
'1'
,
'.'
,
'1'
,
'0'
,
'9'
,
'8'
,
'0'
,
'3'
,
'1'
,
'6'
,
'1'
,
'2'
,
0
,
0
};
u8
test_parttern2
[
40
]
=
{
0
};
pdc20621_put_to_dimm
(
pe
,
(
void
*
)
test_parttern2
,
0x10040
,
40
);
pdc20621_put_to_dimm
(
pe
,
(
void
*
)
test_parttern2
,
0x40
,
40
);
pdc20621_put_to_dimm
(
pe
,
(
void
*
)
test_parttern1
,
0x10040
,
40
);
pdc20621_get_from_dimm
(
pe
,
(
void
*
)
test_parttern2
,
0x40
,
40
);
printk
(
KERN_ERR
"%x, %x, %s
\n
"
,
test_parttern2
[
0
],
test_parttern2
[
1
],
&
(
test_parttern2
[
2
]));
pdc20621_get_from_dimm
(
pe
,
(
void
*
)
test_parttern2
,
0x10040
,
40
);
printk
(
KERN_ERR
"%x, %x, %s
\n
"
,
test_parttern2
[
0
],
test_parttern2
[
1
],
&
(
test_parttern2
[
2
]));
pdc20621_put_to_dimm
(
pe
,
(
void
*
)
test_parttern1
,
0x40
,
40
);
pdc20621_get_from_dimm
(
pe
,
(
void
*
)
test_parttern2
,
0x40
,
40
);
printk
(
KERN_ERR
"%x, %x, %s
\n
"
,
test_parttern2
[
0
],
test_parttern2
[
1
],
&
(
test_parttern2
[
2
]));
}
#endif
/* ECC initiliazation. */
pdc20621_i2c_read
(
pe
,
PDC_DIMM0_SPD_DEV_ADDRESS
,
PDC_DIMM_SPD_TYPE
,
&
spd0
);
if
(
spd0
==
0x02
)
{
VPRINTK
(
"Start ECC initialization
\n
"
);
addr
=
0
;
length
=
size
*
1024
*
1024
;
while
(
addr
<
length
)
{
pdc20621_put_to_dimm
(
pe
,
(
void
*
)
&
tmp
,
addr
,
sizeof
(
u32
));
addr
+=
sizeof
(
u32
);
}
VPRINTK
(
"Finish ECC initialization
\n
"
);
}
return
0
;
}
static
void
pdc_20621_init
(
struct
ata_probe_ent
*
pe
)
{
u32
tmp
;
void
*
mmio
=
pe
->
mmio_base
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
/*
* Select page 0x40 for our 32k DIMM window
*/
tmp
=
readl
(
mmio
+
PDC_20621_DIMM_WINDOW
)
&
0xffff0000
;
tmp
|=
PDC_PAGE_WINDOW
;
/* page 40h; arbitrarily selected */
writel
(
tmp
,
mmio
+
PDC_20621_DIMM_WINDOW
);
/*
* Reset Host DMA
*/
tmp
=
readl
(
mmio
+
PDC_HDMA_CTLSTAT
);
tmp
|=
PDC_RESET
;
writel
(
tmp
,
mmio
+
PDC_HDMA_CTLSTAT
);
readl
(
mmio
+
PDC_HDMA_CTLSTAT
);
/* flush */
udelay
(
10
);
tmp
=
readl
(
mmio
+
PDC_HDMA_CTLSTAT
);
tmp
&=
~
PDC_RESET
;
writel
(
tmp
,
mmio
+
PDC_HDMA_CTLSTAT
);
readl
(
mmio
+
PDC_HDMA_CTLSTAT
);
/* flush */
}
static
void
pdc_host_init
(
unsigned
int
chip_id
,
struct
ata_probe_ent
*
pe
)
{
void
*
mmio
=
pe
->
mmio_base
;
u32
tmp
;
if
(
chip_id
==
board_20621
)
BUG
();
/*
* Except for the hotplug stuff, this is voodoo from the
* Promise driver. Label this entire section
...
...
@@ -1701,10 +646,8 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
static
int
printed_version
;
struct
ata_probe_ent
*
probe_ent
=
NULL
;
unsigned
long
base
;
void
*
mmio_base
,
*
dimm_mmio
=
NULL
;
struct
pdc_host_priv
*
hpriv
=
NULL
;
void
*
mmio_base
;
unsigned
int
board_idx
=
(
unsigned
int
)
ent
->
driver_data
;
unsigned
int
have_20621
=
(
board_idx
==
board_20621
);
int
rc
;
if
(
!
printed_version
++
)
...
...
@@ -1747,25 +690,6 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
}
base
=
(
unsigned
long
)
mmio_base
;
if
(
have_20621
)
{
hpriv
=
kmalloc
(
sizeof
(
*
hpriv
),
GFP_KERNEL
);
if
(
!
hpriv
)
{
rc
=
-
ENOMEM
;
goto
err_out_iounmap
;
}
memset
(
hpriv
,
0
,
sizeof
(
*
hpriv
));
dimm_mmio
=
ioremap
(
pci_resource_start
(
pdev
,
4
),
pci_resource_len
(
pdev
,
4
));
if
(
!
dimm_mmio
)
{
kfree
(
hpriv
);
rc
=
-
ENOMEM
;
goto
err_out_iounmap
;
}
hpriv
->
dimm_mmio
=
dimm_mmio
;
}
probe_ent
->
sht
=
pdc_port_info
[
board_idx
].
sht
;
probe_ent
->
host_flags
=
pdc_port_info
[
board_idx
].
host_flags
;
probe_ent
->
pio_mask
=
pdc_port_info
[
board_idx
].
pio_mask
;
...
...
@@ -1776,32 +700,22 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
probe_ent
->
irq_flags
=
SA_SHIRQ
;
probe_ent
->
mmio_base
=
mmio_base
;
if
(
have_20621
)
{
probe_ent
->
private_data
=
hpriv
;
base
+=
PDC_CHIP0_OFS
;
}
pdc_sata_setup_port
(
&
probe_ent
->
port
[
0
],
base
+
0x200
);
pdc_sata_setup_port
(
&
probe_ent
->
port
[
1
],
base
+
0x280
);
if
(
!
have_20621
)
{
probe_ent
->
port
[
0
].
scr_addr
=
base
+
0x400
;
probe_ent
->
port
[
1
].
scr_addr
=
base
+
0x500
;
}
probe_ent
->
port
[
0
].
scr_addr
=
base
+
0x400
;
probe_ent
->
port
[
1
].
scr_addr
=
base
+
0x500
;
/* notice 4-port boards */
switch
(
board_idx
)
{
case
board_20319
:
case
board_20621
:
probe_ent
->
n_ports
=
4
;
pdc_sata_setup_port
(
&
probe_ent
->
port
[
2
],
base
+
0x300
);
pdc_sata_setup_port
(
&
probe_ent
->
port
[
3
],
base
+
0x380
);
if
(
!
have_20621
)
{
probe_ent
->
port
[
2
].
scr_addr
=
base
+
0x600
;
probe_ent
->
port
[
3
].
scr_addr
=
base
+
0x700
;
}
probe_ent
->
port
[
2
].
scr_addr
=
base
+
0x600
;
probe_ent
->
port
[
3
].
scr_addr
=
base
+
0x700
;
break
;
case
board_2037x
:
probe_ent
->
n_ports
=
2
;
...
...
@@ -1814,15 +728,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
pci_set_master
(
pdev
);
/* initialize adapter */
if
(
have_20621
)
{
/* initialize local dimm */
if
(
pdc20621_dimm_init
(
probe_ent
))
{
rc
=
-
ENOMEM
;
goto
err_out_iounmap_dimm
;
}
pdc_20621_init
(
probe_ent
);
}
else
pdc_host_init
(
board_idx
,
probe_ent
);
pdc_host_init
(
board_idx
,
probe_ent
);
/* FIXME: check ata_device_add return value */
ata_device_add
(
probe_ent
);
...
...
@@ -1830,11 +736,6 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
return
0
;
err_out_iounmap_dimm:
/* only get to this label if 20621 */
kfree
(
hpriv
);
iounmap
(
dimm_mmio
);
err_out_iounmap:
iounmap
(
mmio_base
);
err_out_free_ent:
kfree
(
probe_ent
);
err_out_regions:
...
...
@@ -1858,7 +759,7 @@ static void __exit pdc_sata_exit(void)
MODULE_AUTHOR
(
"Jeff Garzik"
);
MODULE_DESCRIPTION
(
"Promise SATA low-level driver"
);
MODULE_DESCRIPTION
(
"Promise SATA
TX2/TX4
low-level driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DEVICE_TABLE
(
pci
,
pdc_sata_pci_tbl
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment