xref: /OK3568_Linux_fs/u-boot/drivers/spi/altera_spi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Altera SPI driver
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * based on bfin_spi.c
5*4882a593Smuzhiyun  * Copyright (c) 2005-2008 Analog Devices Inc.
6*4882a593Smuzhiyun  * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun #include <common.h>
11*4882a593Smuzhiyun #include <dm.h>
12*4882a593Smuzhiyun #include <errno.h>
13*4882a593Smuzhiyun #include <malloc.h>
14*4882a593Smuzhiyun #include <fdtdec.h>
15*4882a593Smuzhiyun #include <spi.h>
16*4882a593Smuzhiyun #include <asm/io.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #define ALTERA_SPI_STATUS_RRDY_MSK	BIT(7)
21*4882a593Smuzhiyun #define ALTERA_SPI_CONTROL_SSO_MSK	BIT(10)
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #ifndef CONFIG_ALTERA_SPI_IDLE_VAL
24*4882a593Smuzhiyun #define CONFIG_ALTERA_SPI_IDLE_VAL	0xff
25*4882a593Smuzhiyun #endif
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun struct altera_spi_regs {
28*4882a593Smuzhiyun 	u32	rxdata;
29*4882a593Smuzhiyun 	u32	txdata;
30*4882a593Smuzhiyun 	u32	status;
31*4882a593Smuzhiyun 	u32	control;
32*4882a593Smuzhiyun 	u32	_reserved;
33*4882a593Smuzhiyun 	u32	slave_sel;
34*4882a593Smuzhiyun };
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun struct altera_spi_platdata {
37*4882a593Smuzhiyun 	struct altera_spi_regs *regs;
38*4882a593Smuzhiyun };
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun struct altera_spi_priv {
41*4882a593Smuzhiyun 	struct altera_spi_regs *regs;
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
spi_cs_activate(struct udevice * dev,uint cs)44*4882a593Smuzhiyun static void spi_cs_activate(struct udevice *dev, uint cs)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun 	struct udevice *bus = dev->parent;
47*4882a593Smuzhiyun 	struct altera_spi_priv *priv = dev_get_priv(bus);
48*4882a593Smuzhiyun 	struct altera_spi_regs *const regs = priv->regs;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	writel(1 << cs, &regs->slave_sel);
51*4882a593Smuzhiyun 	writel(ALTERA_SPI_CONTROL_SSO_MSK, &regs->control);
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
spi_cs_deactivate(struct udevice * dev)54*4882a593Smuzhiyun static void spi_cs_deactivate(struct udevice *dev)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	struct udevice *bus = dev->parent;
57*4882a593Smuzhiyun 	struct altera_spi_priv *priv = dev_get_priv(bus);
58*4882a593Smuzhiyun 	struct altera_spi_regs *const regs = priv->regs;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	writel(0, &regs->control);
61*4882a593Smuzhiyun 	writel(0, &regs->slave_sel);
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun 
altera_spi_claim_bus(struct udevice * dev)64*4882a593Smuzhiyun static int altera_spi_claim_bus(struct udevice *dev)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 	struct udevice *bus = dev->parent;
67*4882a593Smuzhiyun 	struct altera_spi_priv *priv = dev_get_priv(bus);
68*4882a593Smuzhiyun 	struct altera_spi_regs *const regs = priv->regs;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	writel(0, &regs->control);
71*4882a593Smuzhiyun 	writel(0, &regs->slave_sel);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	return 0;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun 
altera_spi_release_bus(struct udevice * dev)76*4882a593Smuzhiyun static int altera_spi_release_bus(struct udevice *dev)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun 	struct udevice *bus = dev->parent;
79*4882a593Smuzhiyun 	struct altera_spi_priv *priv = dev_get_priv(bus);
80*4882a593Smuzhiyun 	struct altera_spi_regs *const regs = priv->regs;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	writel(0, &regs->slave_sel);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	return 0;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
altera_spi_xfer(struct udevice * dev,unsigned int bitlen,const void * dout,void * din,unsigned long flags)87*4882a593Smuzhiyun static int altera_spi_xfer(struct udevice *dev, unsigned int bitlen,
88*4882a593Smuzhiyun 			    const void *dout, void *din, unsigned long flags)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun 	struct udevice *bus = dev->parent;
91*4882a593Smuzhiyun 	struct altera_spi_priv *priv = dev_get_priv(bus);
92*4882a593Smuzhiyun 	struct altera_spi_regs *const regs = priv->regs;
93*4882a593Smuzhiyun 	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	/* assume spi core configured to do 8 bit transfers */
96*4882a593Smuzhiyun 	unsigned int bytes = bitlen / 8;
97*4882a593Smuzhiyun 	const unsigned char *txp = dout;
98*4882a593Smuzhiyun 	unsigned char *rxp = din;
99*4882a593Smuzhiyun 	uint32_t reg, data, start;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
102*4882a593Smuzhiyun 	      bus->seq, slave_plat->cs, bitlen, bytes, flags);
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	if (bitlen == 0)
105*4882a593Smuzhiyun 		goto done;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	if (bitlen % 8) {
108*4882a593Smuzhiyun 		flags |= SPI_XFER_END;
109*4882a593Smuzhiyun 		goto done;
110*4882a593Smuzhiyun 	}
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	/* empty read buffer */
113*4882a593Smuzhiyun 	if (readl(&regs->status) & ALTERA_SPI_STATUS_RRDY_MSK)
114*4882a593Smuzhiyun 		readl(&regs->rxdata);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	if (flags & SPI_XFER_BEGIN)
117*4882a593Smuzhiyun 		spi_cs_activate(dev, slave_plat->cs);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	while (bytes--) {
120*4882a593Smuzhiyun 		if (txp)
121*4882a593Smuzhiyun 			data = *txp++;
122*4882a593Smuzhiyun 		else
123*4882a593Smuzhiyun 			data = CONFIG_ALTERA_SPI_IDLE_VAL;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 		debug("%s: tx:%x ", __func__, data);
126*4882a593Smuzhiyun 		writel(data, &regs->txdata);
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 		start = get_timer(0);
129*4882a593Smuzhiyun 		while (1) {
130*4882a593Smuzhiyun 			reg = readl(&regs->status);
131*4882a593Smuzhiyun 			if (reg & ALTERA_SPI_STATUS_RRDY_MSK)
132*4882a593Smuzhiyun 				break;
133*4882a593Smuzhiyun 			if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
134*4882a593Smuzhiyun 				debug("%s: Transmission timed out!\n", __func__);
135*4882a593Smuzhiyun 				return -1;
136*4882a593Smuzhiyun 			}
137*4882a593Smuzhiyun 		}
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 		data = readl(&regs->rxdata);
140*4882a593Smuzhiyun 		if (rxp)
141*4882a593Smuzhiyun 			*rxp++ = data & 0xff;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 		debug("rx:%x\n", data);
144*4882a593Smuzhiyun 	}
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun done:
147*4882a593Smuzhiyun 	if (flags & SPI_XFER_END)
148*4882a593Smuzhiyun 		spi_cs_deactivate(dev);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	return 0;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
altera_spi_set_speed(struct udevice * bus,uint speed)153*4882a593Smuzhiyun static int altera_spi_set_speed(struct udevice *bus, uint speed)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	return 0;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun 
altera_spi_set_mode(struct udevice * bus,uint mode)158*4882a593Smuzhiyun static int altera_spi_set_mode(struct udevice *bus, uint mode)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	return 0;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun 
altera_spi_probe(struct udevice * bus)163*4882a593Smuzhiyun static int altera_spi_probe(struct udevice *bus)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun 	struct altera_spi_platdata *plat = dev_get_platdata(bus);
166*4882a593Smuzhiyun 	struct altera_spi_priv *priv = dev_get_priv(bus);
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	priv->regs = plat->regs;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	return 0;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun 
altera_spi_ofdata_to_platdata(struct udevice * bus)173*4882a593Smuzhiyun static int altera_spi_ofdata_to_platdata(struct udevice *bus)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun 	struct altera_spi_platdata *plat = dev_get_platdata(bus);
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	plat->regs = map_physmem(devfdt_get_addr(bus),
178*4882a593Smuzhiyun 				 sizeof(struct altera_spi_regs),
179*4882a593Smuzhiyun 				 MAP_NOCACHE);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	return 0;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun static const struct dm_spi_ops altera_spi_ops = {
185*4882a593Smuzhiyun 	.claim_bus	= altera_spi_claim_bus,
186*4882a593Smuzhiyun 	.release_bus	= altera_spi_release_bus,
187*4882a593Smuzhiyun 	.xfer		= altera_spi_xfer,
188*4882a593Smuzhiyun 	.set_speed	= altera_spi_set_speed,
189*4882a593Smuzhiyun 	.set_mode	= altera_spi_set_mode,
190*4882a593Smuzhiyun 	/*
191*4882a593Smuzhiyun 	 * cs_info is not needed, since we require all chip selects to be
192*4882a593Smuzhiyun 	 * in the device tree explicitly
193*4882a593Smuzhiyun 	 */
194*4882a593Smuzhiyun };
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun static const struct udevice_id altera_spi_ids[] = {
197*4882a593Smuzhiyun 	{ .compatible = "altr,spi-1.0" },
198*4882a593Smuzhiyun 	{}
199*4882a593Smuzhiyun };
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun U_BOOT_DRIVER(altera_spi) = {
202*4882a593Smuzhiyun 	.name	= "altera_spi",
203*4882a593Smuzhiyun 	.id	= UCLASS_SPI,
204*4882a593Smuzhiyun 	.of_match = altera_spi_ids,
205*4882a593Smuzhiyun 	.ops	= &altera_spi_ops,
206*4882a593Smuzhiyun 	.ofdata_to_platdata = altera_spi_ofdata_to_platdata,
207*4882a593Smuzhiyun 	.platdata_auto_alloc_size = sizeof(struct altera_spi_platdata),
208*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct altera_spi_priv),
209*4882a593Smuzhiyun 	.probe	= altera_spi_probe,
210*4882a593Smuzhiyun };
211