5 * Copyright (c) 2005-2008 Analog Devices Inc.
6 * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
8 * SPDX-License-Identifier: GPL-2.0+
18 DECLARE_GLOBAL_DATA_PTR
;
20 #ifndef CONFIG_ALTERA_SPI_IDLE_VAL
21 #define CONFIG_ALTERA_SPI_IDLE_VAL 0xff
24 struct altera_spi_regs
{
33 struct altera_spi_platdata
{
34 struct altera_spi_regs
*regs
;
37 struct altera_spi_priv
{
38 struct altera_spi_regs
*regs
;
41 #define ALTERA_SPI_STATUS_RRDY_MSK BIT(7)
42 #define ALTERA_SPI_CONTROL_SSO_MSK BIT(10)
44 static void spi_cs_activate(struct udevice
*dev
, uint cs
)
46 struct udevice
*bus
= dev
->parent
;
47 struct altera_spi_priv
*priv
= dev_get_priv(bus
);
48 struct altera_spi_regs
*const regs
= priv
->regs
;
50 writel(1 << cs
, ®s
->slave_sel
);
51 writel(ALTERA_SPI_CONTROL_SSO_MSK
, ®s
->control
);
54 static void spi_cs_deactivate(struct udevice
*dev
)
56 struct udevice
*bus
= dev
->parent
;
57 struct altera_spi_priv
*priv
= dev_get_priv(bus
);
58 struct altera_spi_regs
*const regs
= priv
->regs
;
60 writel(0, ®s
->control
);
61 writel(0, ®s
->slave_sel
);
64 static int altera_spi_claim_bus(struct udevice
*dev
)
66 struct udevice
*bus
= dev
->parent
;
67 struct altera_spi_priv
*priv
= dev_get_priv(bus
);
68 struct altera_spi_regs
*const regs
= priv
->regs
;
70 writel(0, ®s
->control
);
71 writel(0, ®s
->slave_sel
);
76 static int altera_spi_release_bus(struct udevice
*dev
)
78 struct udevice
*bus
= dev
->parent
;
79 struct altera_spi_priv
*priv
= dev_get_priv(bus
);
80 struct altera_spi_regs
*const regs
= priv
->regs
;
82 writel(0, ®s
->slave_sel
);
87 static int altera_spi_xfer(struct udevice
*dev
, unsigned int bitlen
,
88 const void *dout
, void *din
, unsigned long flags
)
90 struct udevice
*bus
= dev
->parent
;
91 struct altera_spi_priv
*priv
= dev_get_priv(bus
);
92 struct altera_spi_regs
*const regs
= priv
->regs
;
93 struct dm_spi_slave_platdata
*slave_plat
= dev_get_parent_platdata(dev
);
95 /* assume spi core configured to do 8 bit transfers */
96 unsigned int bytes
= bitlen
/ 8;
97 const unsigned char *txp
= dout
;
98 unsigned char *rxp
= din
;
99 uint32_t reg
, data
, start
;
101 debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__
,
102 bus
->seq
, slave_plat
->cs
, bitlen
, bytes
, flags
);
108 flags
|= SPI_XFER_END
;
112 /* empty read buffer */
113 if (readl(®s
->status
) & ALTERA_SPI_STATUS_RRDY_MSK
)
114 readl(®s
->rxdata
);
116 if (flags
& SPI_XFER_BEGIN
)
117 spi_cs_activate(dev
, slave_plat
->cs
);
123 data
= CONFIG_ALTERA_SPI_IDLE_VAL
;
125 debug("%s: tx:%x ", __func__
, data
);
126 writel(data
, ®s
->txdata
);
128 start
= get_timer(0);
130 reg
= readl(®s
->status
);
131 if (reg
& ALTERA_SPI_STATUS_RRDY_MSK
)
133 if (get_timer(start
) > (CONFIG_SYS_HZ
/ 1000)) {
134 debug("%s: Transmission timed out!\n", __func__
);
139 data
= readl(®s
->rxdata
);
141 *rxp
++ = data
& 0xff;
143 debug("rx:%x\n", data
);
147 if (flags
& SPI_XFER_END
)
148 spi_cs_deactivate(dev
);
153 static int altera_spi_set_speed(struct udevice
*bus
, uint speed
)
158 static int altera_spi_set_mode(struct udevice
*bus
, uint mode
)
163 static int altera_spi_probe(struct udevice
*bus
)
165 struct altera_spi_platdata
*plat
= dev_get_platdata(bus
);
166 struct altera_spi_priv
*priv
= dev_get_priv(bus
);
168 priv
->regs
= plat
->regs
;
173 static int altera_spi_ofdata_to_platdata(struct udevice
*bus
)
175 struct altera_spi_platdata
*plat
= dev_get_platdata(bus
);
177 plat
->regs
= ioremap(dev_get_addr(bus
),
178 sizeof(struct altera_spi_regs
));
183 static const struct dm_spi_ops altera_spi_ops
= {
184 .claim_bus
= altera_spi_claim_bus
,
185 .release_bus
= altera_spi_release_bus
,
186 .xfer
= altera_spi_xfer
,
187 .set_speed
= altera_spi_set_speed
,
188 .set_mode
= altera_spi_set_mode
,
190 * cs_info is not needed, since we require all chip selects to be
191 * in the device tree explicitly
195 static const struct udevice_id altera_spi_ids
[] = {
196 { .compatible
= "altr,spi-1.0", },
200 U_BOOT_DRIVER(altera_spi
) = {
201 .name
= "altera_spi",
203 .of_match
= altera_spi_ids
,
204 .ops
= &altera_spi_ops
,
205 .ofdata_to_platdata
= altera_spi_ofdata_to_platdata
,
206 .platdata_auto_alloc_size
= sizeof(struct altera_spi_platdata
),
207 .priv_auto_alloc_size
= sizeof(struct altera_spi_priv
),
208 .probe
= altera_spi_probe
,