aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/intel_mid_ssp_spi.h
blob: aef2fa8973bc8fc80910c38285a65bbea4d729f7 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
/*
 *  Copyright (C) Intel 2009
 *  Ken Mills <ken.k.mills@intel.com>
 *  Sylvain Centelles <sylvain.centelles@intel.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 of the License, 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, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 */
#ifndef INTEL_MID_SSP_SPI_H_
#define INTEL_MID_SSP_SPI_H_

#define PCI_MRST_DMAC1_ID	0x0814
#define PCI_MDFL_DMAC1_ID	0x0827

#define SSP_NOT_SYNC 0x400000
#define MAX_SPI_TRANSFER_SIZE 8192
#define MAX_BITBANGING_LOOP   10000
#define SPI_FIFO_SIZE 16

/* PM QoS define */
#define MIN_EXIT_LATENCY 20

/* SSP assignement configuration from PCI config */
#define SSP_CFG_GET_MODE(ssp_cfg)	((ssp_cfg) & 0x07)
#define SSP_CFG_GET_SPI_BUS_NB(ssp_cfg)	(((ssp_cfg) >> 3) & 0x07)
#define SSP_CFG_IS_SPI_SLAVE(ssp_cfg)	((ssp_cfg) & 0x40)
#define SSP_CFG_SPI_MODE_ID		1
/* adid field offset is 6 inside the vendor specific capability */
#define VNDR_CAPABILITY_ADID_OFFSET	6

/* Driver's quirk flags */
/* This workarround bufferizes data in the audio fabric SDRAM from  */
/* where the DMA transfers will operate. Should be enabled only for */
/* SPI slave mode.                                                  */
#define QUIRKS_SRAM_ADDITIONAL_CPY	1
/* If set the trailing bytes won't be handled by the DMA.           */
/* Trailing byte feature not fully available.                       */
#define QUIRKS_DMA_USE_NO_TRAIL		2
/* If set, the driver will use PM_QOS to reduce the latency         */
/* introduced by the deeper C-states which may produce over/under   */
/* run issues. Must be used in slave mode. In master mode, the      */
/* latency is not critical, but setting this workarround  may       */
/* improve the SPI throughput.                                      */
#define QUIRKS_USE_PM_QOS		4
/* This quirks is set on Moorestown                                 */
#define QUIRKS_PLATFORM_MRST		8
/* This quirks is set on Medfield                                   */
#define QUIRKS_PLATFORM_MDFL		16
/* If set, the driver will apply the bitbanging workarround needed  */
/* to enable defective Langwell stepping A SSP. The defective SSP   */
/* can be enabled only once, and should never be disabled.          */
#define QUIRKS_BIT_BANGING		32
/* If set, SPI is in slave clock mode                               */
#define QUIRKS_SPI_SLAVE_CLOCK_MODE	64

/* Uncomment to get RX and TX short dumps after each transfer */
/* #define DUMP_RX 1 */
#define MAX_TRAILING_BYTE_RETRY 16
#define MAX_TRAILING_BYTE_LOOP 100
#define DELAY_TO_GET_A_WORD 3
#define DFLT_TIMEOUT_VAL 500

#define DEFINE_SSP_REG(reg, off) \
static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \
static inline void write_##reg(u32 v, void *p) { __raw_writel(v, p + (off)); }

#define RX_DIRECTION 0
#define TX_DIRECTION 1

#define I2C_ACCESS_USDELAY 10

#define DFLT_BITS_PER_WORD 16
#define MIN_BITS_PER_WORD     4
#define MAX_BITS_PER_WORD     32
#define DFLT_FIFO_BURST_SIZE	IMSS_FIFO_BURST_8

#define TRUNCATE(x, a) ((x) & ~((a)-1))

DEFINE_SSP_REG(SSCR0, 0x00)
DEFINE_SSP_REG(SSCR1, 0x04)
DEFINE_SSP_REG(SSSR, 0x08)
DEFINE_SSP_REG(SSITR, 0x0c)
DEFINE_SSP_REG(SSDR, 0x10)
DEFINE_SSP_REG(SSTO, 0x28)
DEFINE_SSP_REG(SSPSP, 0x2c)

DEFINE_SSP_REG(I2CCTRL, 0x00);
DEFINE_SSP_REG(I2CDATA, 0x04);

DEFINE_SSP_REG(GPLR1, 0x04);
DEFINE_SSP_REG(GPDR1, 0x0c);
DEFINE_SSP_REG(GPSR1, 0x14);
DEFINE_SSP_REG(GPCR1, 0x1C);
DEFINE_SSP_REG(GAFR1_U, 0x44);

#define SYSCFG  0x20bc0

#define SRAM_BASE_ADDR 0xfffdc000
#define SRAM_RX_ADDR   SRAM_BASE_ADDR
#define SRAM_TX_ADDR  (SRAM_BASE_ADDR + MAX_SPI_TRANSFER_SIZE)

#define SSCR0_DSS   (0x0000000f)     /* Data Size Select (mask) */
#define SSCR0_DataSize(x)  ((x) - 1)    /* Data Size Select [4..16] */
#define SSCR0_FRF   (0x00000030)     /* FRame Format (mask) */
#define SSCR0_Motorola        (0x0 << 4)         /* Motorola's SPI mode */
#define SSCR0_ECS   (1 << 6) /* External clock select */
#define SSCR0_SSE   (1 << 7) /* Synchronous Serial Port Enable */

#define SSCR0_SCR   (0x000fff00)      /* Serial Clock Rate (mask) */
#define SSCR0_SerClkDiv(x) (((x) - 1) << 8) /* Divisor [1..4096] */
#define SSCR0_EDSS  (1 << 20)           /* Extended data size select */
#define SSCR0_NCS   (1 << 21)           /* Network clock select */
#define SSCR0_RIM    (1 << 22)           /* Receive FIFO overrrun int mask */
#define SSCR0_TUM   (1 << 23)           /* Transmit FIFO underrun int mask */
#define SSCR0_FRDC (0x07000000)     /* Frame rate divider control (mask) */
#define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24) /* Time slots per frame */
#define SSCR0_ADC   (1 << 30)           /* Audio clock select */
#define SSCR0_MOD  (1 << 31)           /* Mode (normal or network) */

#define SSCR1_RIE    (1 << 0) /* Receive FIFO Interrupt Enable */
#define SSCR1_TIE     (1 << 1) /* Transmit FIFO Interrupt Enable */
#define SSCR1_LBM   (1 << 2) /* Loop-Back Mode */
#define SSCR1_SPO   (1 << 3) /* SSPSCLK polarity setting */
#define SSCR1_SPH   (1 << 4) /* Motorola SPI SSPSCLK phase setting */
#define SSCR1_MWDS           (1 << 5) /* Microwire Transmit Data Size */
#define SSCR1_TFT    (0x000003c0)     /* Transmit FIFO Threshold (mask) */
#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..16] */
#define SSCR1_RFT    (0x00003c00)     /* Receive FIFO Threshold (mask) */
#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */

#define SSSR_TNF		(1 << 2)	/* Tx FIFO Not Full */
#define SSSR_RNE		(1 << 3)	/* Rx FIFO Not Empty */
#define SSSR_BSY		(1 << 4)	/* SSP Busy */
#define SSSR_TFS		(1 << 5)	/* Tx FIFO Service Request */
#define SSSR_RFS		(1 << 6)	/* Rx FIFO Service Request */
#define SSSR_ROR		(1 << 7)	/* Rx FIFO Overrun */
#define SSSR_TFL_MASK           (0x0F << 8)     /* Tx FIFO level field mask */

#define SSCR0_TIM    (1 << 23)          /* Transmit FIFO Under Run Int Mask */
#define SSCR0_RIM    (1 << 22)          /* Receive FIFO Over Run int Mask */
#define SSCR0_NCS    (1 << 21)          /* Network Clock Select */
#define SSCR0_EDSS   (1 << 20)          /* Extended Data Size Select */

#define SSCR0_TISSP      (1 << 4)  /* TI Sync Serial Protocol */
#define SSCR0_PSP        (3 << 4)  /* PSP - Programmable Serial Protocol */
#define SSCR1_TTELP      (1 << 31) /* TXD Tristate Enable Last Phase */
#define SSCR1_TTE        (1 << 30) /* TXD Tristate Enable */
#define SSCR1_EBCEI      (1 << 29) /* Enable Bit Count Error interrupt */
#define SSCR1_SCFR       (1 << 28) /* Slave Clock free Running */
#define SSCR1_ECRA       (1 << 27) /* Enable Clock Request A */
#define SSCR1_ECRB       (1 << 26) /* Enable Clock request B */
#define SSCR1_SCLKDIR    (1 << 25) /* Serial Bit Rate Clock Direction */
#define SSCR1_SFRMDIR    (1 << 24) /* Frame Direction */
#define SSCR1_RWOT       (1 << 23) /* Receive Without Transmit */
#define SSCR1_TRAIL      (1 << 22) /* Trailing Byte */
#define SSCR1_TSRE       (1 << 21) /* Transmit Service Request Enable */
#define SSCR1_RSRE       (1 << 20) /* Receive Service Request Enable */
#define SSCR1_TINTE      (1 << 19) /* Receiver Time-out Interrupt enable */
#define SSCR1_PINTE      (1 << 18) /* Trailing Byte Interupt Enable */
#define SSCR1_STRF       (1 << 15) /* Select FIFO or EFWR */
#define SSCR1_EFWR       (1 << 14) /* Enable FIFO Write/Read */
#define SSCR1_IFS        (1 << 16) /* Invert Frame Signal */

#define SSSR_BCE         (1 << 23) /* Bit Count Error */
#define SSSR_CSS         (1 << 22) /* Clock Synchronisation Status */
#define SSSR_TUR         (1 << 21) /* Transmit FIFO Under Run */
#define SSSR_EOC         (1 << 20) /* End Of Chain */
#define SSSR_TINT        (1 << 19) /* Receiver Time-out Interrupt */
#define SSSR_PINT        (1 << 18) /* Peripheral Trailing Byte Interrupt */

#define SSPSP_FSRT       (1 << 25)   /* Frame Sync Relative Timing */
#define SSPSP_DMYSTOP(x) ((x) << 23) /* Dummy Stop */
#define SSPSP_SFRMWDTH(x)((x) << 16) /* Serial Frame Width */
#define SSPSP_SFRMDLY(x) ((x) << 9)  /* Serial Frame Delay */
#define SSPSP_DMYSTRT(x) ((x) << 7)  /* Dummy Start */
#define SSPSP_STRTDLY(x) ((x) << 4)  /* Start Delay */
#define SSPSP_ETDS       (1 << 3)    /* End of Transfer data State */
#define SSPSP_SFRMP      (1 << 2)    /* Serial Frame Polarity */
#define SSPSP_SCMODE(x)  ((x) << 0)  /* Serial Bit Rate Clock Mode */

/*
 * For testing SSCR1 changes that require SSP restart, basically
 * everything except the service and interrupt enables
 */

#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \
				| SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
				| SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
				| SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \
				| SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
				| SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)

struct callback_param {
	void *drv_context;
	u32 direction;
};

struct ssp_driver_context {
	/* Driver model hookup */
	struct pci_dev *pdev;

	/* SPI framework hookup */
	struct spi_master *master;

	/* SSP register addresses */
	unsigned long paddr;
	void *ioaddr;
	int irq;

	/* I2C registers */
	dma_addr_t I2C_paddr;
	void *I2C_ioaddr;

	/* SSP masks*/
	u32 cr1_sig;
	u32 cr1;
	u32 clear_sr;
	u32 mask_sr;

	/* PM_QOS request */
	struct pm_qos_request_list pm_qos_req;

	struct tasklet_struct poll_transfer;

	spinlock_t lock;

	/* Current message transfer state info */
	struct spi_message *cur_msg;
	size_t len;
	size_t len_dma_rx;
	size_t len_dma_tx;
	void *tx;
	void *tx_end;
	void *rx;
	void *rx_end;
	bool dma_initialized;
	int dma_mapped;
	dma_addr_t rx_dma;
	dma_addr_t tx_dma;
	u8 n_bytes;
	int (*write)(struct ssp_driver_context *drv_context);
	int (*read)(struct ssp_driver_context *drv_context);

	struct intel_mid_dma_slave    dmas_tx;
	struct intel_mid_dma_slave    dmas_rx;
	struct dma_chan    *txchan;
	struct dma_chan    *rxchan;
	struct workqueue_struct *dma_wq;
	struct work_struct complete_work;

	u8 __iomem *virt_addr_sram_tx;
	u8 __iomem *virt_addr_sram_rx;

	int txdma_done;
	int rxdma_done;
	struct callback_param tx_param;
	struct callback_param rx_param;
	struct pci_dev *dmac1;

	unsigned long quirks;
	u32 rx_fifo_threshold;
};

struct chip_data {
	u32 cr0;
	u32 cr1;
	u32 timeout;
	u8 n_bytes;
	u8 dma_enabled;
	u8 bits_per_word;
	u32 speed_hz;
	int (*write)(struct ssp_driver_context *drv_context);
	int (*read)(struct ssp_driver_context *drv_context);
};


enum intel_mid_ssp_spi_fifo_burst {
	IMSS_FIFO_BURST_1,
	IMSS_FIFO_BURST_4,
	IMSS_FIFO_BURST_8
};

/* spi_board_info.controller_data for SPI slave devices,
 * copied to spi_device.platform_data ... mostly for dma tuning
 */
struct intel_mid_ssp_spi_chip {
	enum intel_mid_ssp_spi_fifo_burst burst_size;
	u32 timeout;
	u8 enable_loopback;
	u8 dma_enabled;
};


#define SPI_DIB_NAME_LEN  16
#define SPI_DIB_SPEC_INFO_LEN      10

struct spi_dib_header {
	u32       signature;
	u32       length;
	u8         rev;
	u8         checksum;
	u8         dib[0];
} __attribute__((packed));

#endif /*INTEL_MID_SSP_SPI_H_*/