summaryrefslogtreecommitdiff
path: root/xhfc/xhfc_leb.c
blob: 42e7b9d5a99a7f722658da35cb0c3a4479a2732d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* EP80579 LEB: configuration of CS0 for an XHFC-4SU.
 *
 * Copyright (C) 2010,2012  Avencall
 * Author: Guillaume Knispel <gknispel@proformatique.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <linux/module.h>
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/errno.h>

#include "xhfc.h"
#include "xhfc_leb.h"


/* === Registers EXP_TIMING_CSn === */

/* Enable CS */
#define LEB_TCS_CS_EN		(	1u  << 31)

/* Enable parity */
#define LEB_TCS_PAR_EN		(	1u  << 30)

#define LEB_TCS_T1_ADDR_TM(x)	(((x) &  3u) << 28)
#define LEB_TCS_T2_SU_CS_TM(x)	(((x) &  3u) << 26)
#define LEB_TCS_T3_STRB_TM(x)	(((x) & 15u) << 22)
#define LEB_TCS_T4_HOLD_TM(x)	(((x) &  3u) << 20)
#define LEB_TCS_T5_RCVRY_TM(x)	(((x) & 15u) << 16)

#define LEB_TCS_CYC_TYPE(x)	(((x) &  3u) << 14)
#define LEB_TCS_CYC_TYPE_INTEL	LEB_TCS_CYC_TYPE(0)

#define LEB_TCS_CNFG_4_0(x)	(((x) & 31u) <<  9)
#define LEB_TCS_CNFG_512_B	LEB_TCS_CNFG_4_0(0)
#define LEB_TCS_CNFG_1_KiB	LEB_TCS_CNFG_4_0(2)
#define LEB_TCS_CNFG_2_KiB	LEB_TCS_CNFG_4_0(4)
#define LEB_TCS_CNFG_4_KiB	LEB_TCS_CNFG_4_0(6)
#define LEB_TCS_CNFG_8_KiB	LEB_TCS_CNFG_4_0(8)
#define LEB_TCS_CNFG_16_KiB	LEB_TCS_CNFG_4_0(10)
#define LEB_TCS_CNFG_32_KiB	LEB_TCS_CNFG_4_0(12)
#define LEB_TCS_CNFG_64_KiB	LEB_TCS_CNFG_4_0(14)
#define LEB_TCS_CNFG_128_KiB	LEB_TCS_CNFG_4_0(16)
#define LEB_TCS_CNFG_256_KiB	LEB_TCS_CNFG_4_0(18)
#define LEB_TCS_CNFG_512_KiB	LEB_TCS_CNFG_4_0(20)
#define LEB_TCS_CNFG_1_MiB	LEB_TCS_CNFG_4_0(22)
#define LEB_TCS_CNFG_2_MiB	LEB_TCS_CNFG_4_0(24)
#define LEB_TCS_CNFG_4_MiB	LEB_TCS_CNFG_4_0(26)
#define LEB_TCS_CNFG_8_MiB	LEB_TCS_CNFG_4_0(28)
#define LEB_TCS_CNFG_16_MiB	LEB_TCS_CNFG_4_0(30)
/* Now the weird one (which also changes
 *  the memory map of MMBAR if used at least once): */
#define LEB_TCS_CNFG_32_MiB	LEB_TCS_CNFG_4_0(1)

/* Synchronous Intel StrataFlash: */
#define LEB_TCS_SYNC_INTEL	(	1u  <<  8)

/* Target device is an EP80579 (unsupported) */
#define LEB_TCS_EXP_CHIP	(	1u  <<  7)

/* Byte read access to half-word device */
#define LEB_TCS_BYTE_RD16	(	1u  <<  6)

/* For HPI (CS4 to CS7 only)
 * 0 => Polarity low true
 * 1 => Polarity high true
 *
 * Don't set if not HPI
 */
#define LEB_TCS_HRDY_POL	(	1u  <<  5)

/* Enable address/data multiplexing: */
#define LEB_TCS_MUX_EN		(	1u  <<  4)

/* Split transaction on internal bus: */
#define LEB_TCS_SPLT_EN		(	1u  <<  3)

/* bit 2 is rsvd, a 0 must be written at this position */

/* Enable writes: */
#define LEB_TCS_WR_EN		(	1u  <<  1)

/* 8-bit device:
 * 0 => 16-bit-wide data bus
 * 1 => 8-bit data bus */
#define LEB_TCS_BYTE_EN		(	1u  <<  0)

void leb_init(struct xhfc_pi *leb)
{
	struct tlp_leb_regs __iomem *regs = leb->regs;

	writel(   LEB_TCS_CS_EN
		| LEB_TCS_T1_ADDR_TM(3)
		| LEB_TCS_T2_SU_CS_TM(3)
		| LEB_TCS_T3_STRB_TM(3)
		| LEB_TCS_T4_HOLD_TM(3)
		| LEB_TCS_T5_RCVRY_TM(3)
		| LEB_TCS_CYC_TYPE_INTEL
		| LEB_TCS_CNFG_512_B	    /* 256_B does not exist */
		| LEB_TCS_MUX_EN
		| LEB_TCS_SPLT_EN
		| LEB_TCS_WR_EN
		| LEB_TCS_BYTE_EN,
	       &regs->timing_cs[0]);

	writel(   LEB_TCS_CS_EN
		| LEB_TCS_T1_ADDR_TM(3)
		| LEB_TCS_T2_SU_CS_TM(3)
		| LEB_TCS_T3_STRB_TM(3)
		| LEB_TCS_T4_HOLD_TM(3)
		| LEB_TCS_T5_RCVRY_TM(3)
		| LEB_TCS_CYC_TYPE_INTEL
		| LEB_TCS_CNFG_512_B
		| LEB_TCS_SPLT_EN
		| LEB_TCS_WR_EN
		| LEB_TCS_BYTE_EN,
	       &regs->timing_cs[1]);

	/* We are true paranoiacs: */
	(void)readl(&regs->timing_cs[1]);

	/* That's it! :-) */
}