xref: /openbmc/u-boot/drivers/spi/mxs_spi.c (revision 1e52fea3)
1 /*
2  * Freescale i.MX28 SPI driver
3  *
4  * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
5  * on behalf of DENX Software Engineering GmbH
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  *
22  * NOTE: This driver only supports the SPI-controller chipselects,
23  *       GPIO driven chipselects are not supported.
24  */
25 
26 #include <common.h>
27 #include <malloc.h>
28 #include <spi.h>
29 #include <asm/errno.h>
30 #include <asm/io.h>
31 #include <asm/arch/clock.h>
32 #include <asm/arch/imx-regs.h>
33 #include <asm/arch/sys_proto.h>
34 
35 #define	MXS_SPI_MAX_TIMEOUT	1000000
36 #define	MXS_SPI_PORT_OFFSET	0x2000
37 
38 struct mxs_spi_slave {
39 	struct spi_slave	slave;
40 	uint32_t		max_khz;
41 	uint32_t		mode;
42 	struct mx28_ssp_regs	*regs;
43 };
44 
45 static inline struct mxs_spi_slave *to_mxs_slave(struct spi_slave *slave)
46 {
47 	return container_of(slave, struct mxs_spi_slave, slave);
48 }
49 
50 void spi_init(void)
51 {
52 }
53 
54 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
55 				  unsigned int max_hz, unsigned int mode)
56 {
57 	struct mxs_spi_slave *mxs_slave;
58 	uint32_t addr;
59 
60 	if (bus > 3) {
61 		printf("MXS SPI: Max bus number is 3\n");
62 		return NULL;
63 	}
64 
65 	mxs_slave = malloc(sizeof(struct mxs_spi_slave));
66 	if (!mxs_slave)
67 		return NULL;
68 
69 	addr = MXS_SSP0_BASE + (bus * MXS_SPI_PORT_OFFSET);
70 
71 	mxs_slave->slave.bus = bus;
72 	mxs_slave->slave.cs = cs;
73 	mxs_slave->max_khz = max_hz / 1000;
74 	mxs_slave->mode = mode;
75 	mxs_slave->regs = (struct mx28_ssp_regs *)addr;
76 
77 	return &mxs_slave->slave;
78 }
79 
80 void spi_free_slave(struct spi_slave *slave)
81 {
82 	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
83 	free(mxs_slave);
84 }
85 
86 int spi_claim_bus(struct spi_slave *slave)
87 {
88 	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
89 	struct mx28_ssp_regs *ssp_regs = mxs_slave->regs;
90 	uint32_t reg = 0;
91 
92 	mx28_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
93 
94 	writel(SSP_CTRL0_BUS_WIDTH_ONE_BIT, &ssp_regs->hw_ssp_ctrl0);
95 
96 	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
97 	reg |= (mxs_slave->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
98 	reg |= (mxs_slave->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
99 	writel(reg, &ssp_regs->hw_ssp_ctrl1);
100 
101 	writel(0, &ssp_regs->hw_ssp_cmd0);
102 
103 	mx28_set_ssp_busclock(slave->bus, mxs_slave->max_khz);
104 
105 	return 0;
106 }
107 
108 void spi_release_bus(struct spi_slave *slave)
109 {
110 }
111 
112 static void mxs_spi_start_xfer(struct mx28_ssp_regs *ssp_regs)
113 {
114 	writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_set);
115 	writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_clr);
116 }
117 
118 static void mxs_spi_end_xfer(struct mx28_ssp_regs *ssp_regs)
119 {
120 	writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_clr);
121 	writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_set);
122 }
123 
124 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
125 		const void *dout, void *din, unsigned long flags)
126 {
127 	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
128 	struct mx28_ssp_regs *ssp_regs = mxs_slave->regs;
129 	int len = bitlen / 8;
130 	const char *tx = dout;
131 	char *rx = din;
132 	char dummy;
133 
134 	if (bitlen == 0) {
135 		if (flags & SPI_XFER_END) {
136 			rx = &dummy;
137 			len = 1;
138 		} else
139 			return 0;
140 	}
141 
142 	if (!rx && !tx)
143 		return 0;
144 
145 	if (flags & SPI_XFER_BEGIN)
146 		mxs_spi_start_xfer(ssp_regs);
147 
148 	while (len--) {
149 		/* We transfer 1 byte */
150 		writel(1, &ssp_regs->hw_ssp_xfer_size);
151 
152 		if ((flags & SPI_XFER_END) && !len)
153 			mxs_spi_end_xfer(ssp_regs);
154 
155 		if (tx)
156 			writel(SSP_CTRL0_READ, &ssp_regs->hw_ssp_ctrl0_clr);
157 		else
158 			writel(SSP_CTRL0_READ, &ssp_regs->hw_ssp_ctrl0_set);
159 
160 		writel(SSP_CTRL0_RUN, &ssp_regs->hw_ssp_ctrl0_set);
161 
162 		if (mx28_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg,
163 			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
164 			printf("MXS SPI: Timeout waiting for start\n");
165 			return -ETIMEDOUT;
166 		}
167 
168 		if (tx)
169 			writel(*tx++, &ssp_regs->hw_ssp_data);
170 
171 		writel(SSP_CTRL0_DATA_XFER, &ssp_regs->hw_ssp_ctrl0_set);
172 
173 		if (rx) {
174 			if (mx28_wait_mask_clr(&ssp_regs->hw_ssp_status_reg,
175 				SSP_STATUS_FIFO_EMPTY, MXS_SPI_MAX_TIMEOUT)) {
176 				printf("MXS SPI: Timeout waiting for data\n");
177 				return -ETIMEDOUT;
178 			}
179 
180 			*rx = readl(&ssp_regs->hw_ssp_data);
181 			rx++;
182 		}
183 
184 		if (mx28_wait_mask_clr(&ssp_regs->hw_ssp_ctrl0_reg,
185 			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
186 			printf("MXS SPI: Timeout waiting for finish\n");
187 			return -ETIMEDOUT;
188 		}
189 	}
190 
191 	return 0;
192 }
193