1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw>
7 * Based on spi_s3c24xx.c, which is:
8 * Copyright (c) 2006 Ben Dooks
9 * Copyright (c) 2006 Simtec Electronics
10 * Ben Dooks <ben@simtec.co.uk>
13 #include <linux/interrupt.h>
14 #include <linux/errno.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/spi/altera.h>
18 #include <linux/spi/spi.h>
22 #define DRV_NAME "spi_altera"
24 #define ALTERA_SPI_RXDATA 0
25 #define ALTERA_SPI_TXDATA 4
26 #define ALTERA_SPI_STATUS 8
27 #define ALTERA_SPI_CONTROL 12
28 #define ALTERA_SPI_SLAVE_SEL 20
30 #define ALTERA_SPI_STATUS_ROE_MSK 0x8
31 #define ALTERA_SPI_STATUS_TOE_MSK 0x10
32 #define ALTERA_SPI_STATUS_TMT_MSK 0x20
33 #define ALTERA_SPI_STATUS_TRDY_MSK 0x40
34 #define ALTERA_SPI_STATUS_RRDY_MSK 0x80
35 #define ALTERA_SPI_STATUS_E_MSK 0x100
37 #define ALTERA_SPI_CONTROL_IROE_MSK 0x8
38 #define ALTERA_SPI_CONTROL_ITOE_MSK 0x10
39 #define ALTERA_SPI_CONTROL_ITRDY_MSK 0x40
40 #define ALTERA_SPI_CONTROL_IRRDY_MSK 0x80
41 #define ALTERA_SPI_CONTROL_IE_MSK 0x100
42 #define ALTERA_SPI_CONTROL_SSO_MSK 0x400
44 #define ALTERA_SPI_MAX_CS 32
46 enum altera_spi_type
{
47 ALTERA_SPI_TYPE_UNKNOWN
,
48 ALTERA_SPI_TYPE_SUBDEV
,
59 const unsigned char *tx
;
62 struct regmap
*regmap
;
67 static const struct regmap_config spi_altera_config
= {
74 static int altr_spi_writel(struct altera_spi
*hw
, unsigned int reg
,
79 ret
= regmap_write(hw
->regmap
, hw
->regoff
+ reg
, val
);
81 dev_err(hw
->dev
, "fail to write reg 0x%x val 0x%x: %d\n",
87 static int altr_spi_readl(struct altera_spi
*hw
, unsigned int reg
,
92 ret
= regmap_read(hw
->regmap
, hw
->regoff
+ reg
, val
);
94 dev_err(hw
->dev
, "fail to read reg 0x%x: %d\n", reg
, ret
);
99 static inline struct altera_spi
*altera_spi_to_hw(struct spi_device
*sdev
)
101 return spi_master_get_devdata(sdev
->master
);
104 static void altera_spi_set_cs(struct spi_device
*spi
, bool is_high
)
106 struct altera_spi
*hw
= altera_spi_to_hw(spi
);
109 hw
->imr
&= ~ALTERA_SPI_CONTROL_SSO_MSK
;
110 altr_spi_writel(hw
, ALTERA_SPI_CONTROL
, hw
->imr
);
111 altr_spi_writel(hw
, ALTERA_SPI_SLAVE_SEL
, 0);
113 altr_spi_writel(hw
, ALTERA_SPI_SLAVE_SEL
,
114 BIT(spi
->chip_select
));
115 hw
->imr
|= ALTERA_SPI_CONTROL_SSO_MSK
;
116 altr_spi_writel(hw
, ALTERA_SPI_CONTROL
, hw
->imr
);
120 static void altera_spi_tx_word(struct altera_spi
*hw
)
122 unsigned int txd
= 0;
125 switch (hw
->bytes_per_word
) {
127 txd
= hw
->tx
[hw
->count
];
130 txd
= (hw
->tx
[hw
->count
* 2]
131 | (hw
->tx
[hw
->count
* 2 + 1] << 8));
134 txd
= (hw
->tx
[hw
->count
* 4]
135 | (hw
->tx
[hw
->count
* 4 + 1] << 8)
136 | (hw
->tx
[hw
->count
* 4 + 2] << 16)
137 | (hw
->tx
[hw
->count
* 4 + 3] << 24));
143 altr_spi_writel(hw
, ALTERA_SPI_TXDATA
, txd
);
146 static void altera_spi_rx_word(struct altera_spi
*hw
)
150 altr_spi_readl(hw
, ALTERA_SPI_RXDATA
, &rxd
);
152 switch (hw
->bytes_per_word
) {
154 hw
->rx
[hw
->count
] = rxd
;
157 hw
->rx
[hw
->count
* 2] = rxd
;
158 hw
->rx
[hw
->count
* 2 + 1] = rxd
>> 8;
161 hw
->rx
[hw
->count
* 4] = rxd
;
162 hw
->rx
[hw
->count
* 4 + 1] = rxd
>> 8;
163 hw
->rx
[hw
->count
* 4 + 2] = rxd
>> 16;
164 hw
->rx
[hw
->count
* 4 + 3] = rxd
>> 24;
173 static int altera_spi_txrx(struct spi_master
*master
,
174 struct spi_device
*spi
, struct spi_transfer
*t
)
176 struct altera_spi
*hw
= spi_master_get_devdata(master
);
182 hw
->bytes_per_word
= DIV_ROUND_UP(t
->bits_per_word
, 8);
183 hw
->len
= t
->len
/ hw
->bytes_per_word
;
186 /* enable receive interrupt */
187 hw
->imr
|= ALTERA_SPI_CONTROL_IRRDY_MSK
;
188 altr_spi_writel(hw
, ALTERA_SPI_CONTROL
, hw
->imr
);
190 /* send the first byte */
191 altera_spi_tx_word(hw
);
193 while (hw
->count
< hw
->len
) {
194 altera_spi_tx_word(hw
);
197 altr_spi_readl(hw
, ALTERA_SPI_STATUS
, &val
);
198 if (val
& ALTERA_SPI_STATUS_RRDY_MSK
)
204 altera_spi_rx_word(hw
);
206 spi_finalize_current_transfer(master
);
212 static irqreturn_t
altera_spi_irq(int irq
, void *dev
)
214 struct spi_master
*master
= dev
;
215 struct altera_spi
*hw
= spi_master_get_devdata(master
);
217 altera_spi_rx_word(hw
);
219 if (hw
->count
< hw
->len
) {
220 altera_spi_tx_word(hw
);
222 /* disable receive interrupt */
223 hw
->imr
&= ~ALTERA_SPI_CONTROL_IRRDY_MSK
;
224 altr_spi_writel(hw
, ALTERA_SPI_CONTROL
, hw
->imr
);
226 spi_finalize_current_transfer(master
);
232 static int altera_spi_probe(struct platform_device
*pdev
)
234 const struct platform_device_id
*platid
= platform_get_device_id(pdev
);
235 struct altera_spi_platform_data
*pdata
= dev_get_platdata(&pdev
->dev
);
236 enum altera_spi_type type
= ALTERA_SPI_TYPE_UNKNOWN
;
237 struct altera_spi
*hw
;
238 struct spi_master
*master
;
243 master
= spi_alloc_master(&pdev
->dev
, sizeof(struct altera_spi
));
247 /* setup the master state. */
248 master
->bus_num
= pdev
->id
;
251 if (pdata
->num_chipselect
> ALTERA_SPI_MAX_CS
) {
253 "Invalid number of chipselect: %hu\n",
254 pdata
->num_chipselect
);
258 master
->num_chipselect
= pdata
->num_chipselect
;
259 master
->mode_bits
= pdata
->mode_bits
;
260 master
->bits_per_word_mask
= pdata
->bits_per_word_mask
;
262 master
->num_chipselect
= 16;
263 master
->mode_bits
= SPI_CS_HIGH
;
264 master
->bits_per_word_mask
= SPI_BPW_RANGE_MASK(1, 16);
267 master
->dev
.of_node
= pdev
->dev
.of_node
;
268 master
->transfer_one
= altera_spi_txrx
;
269 master
->set_cs
= altera_spi_set_cs
;
271 hw
= spi_master_get_devdata(master
);
272 hw
->dev
= &pdev
->dev
;
275 type
= platid
->driver_data
;
277 /* find and map our resources */
278 if (type
== ALTERA_SPI_TYPE_SUBDEV
) {
279 struct resource
*regoff
;
281 hw
->regmap
= dev_get_regmap(pdev
->dev
.parent
, NULL
);
283 dev_err(&pdev
->dev
, "get regmap failed\n");
287 regoff
= platform_get_resource(pdev
, IORESOURCE_REG
, 0);
289 hw
->regoff
= regoff
->start
;
293 res
= devm_platform_ioremap_resource(pdev
, 0);
299 hw
->regmap
= devm_regmap_init_mmio(&pdev
->dev
, res
,
301 if (IS_ERR(hw
->regmap
)) {
302 dev_err(&pdev
->dev
, "regmap mmio init failed\n");
303 err
= PTR_ERR(hw
->regmap
);
308 /* program defaults into the registers */
309 hw
->imr
= 0; /* disable spi interrupts */
310 altr_spi_writel(hw
, ALTERA_SPI_CONTROL
, hw
->imr
);
311 altr_spi_writel(hw
, ALTERA_SPI_STATUS
, 0); /* clear status reg */
312 altr_spi_readl(hw
, ALTERA_SPI_STATUS
, &val
);
313 if (val
& ALTERA_SPI_STATUS_RRDY_MSK
)
314 altr_spi_readl(hw
, ALTERA_SPI_RXDATA
, &val
); /* flush rxdata */
315 /* irq is optional */
316 hw
->irq
= platform_get_irq(pdev
, 0);
318 err
= devm_request_irq(&pdev
->dev
, hw
->irq
, altera_spi_irq
, 0,
324 err
= devm_spi_register_master(&pdev
->dev
, master
);
329 for (i
= 0; i
< pdata
->num_devices
; i
++) {
330 if (!spi_new_device(master
, pdata
->devices
+ i
))
332 "unable to create SPI device: %s\n",
333 pdata
->devices
[i
].modalias
);
337 dev_info(&pdev
->dev
, "regoff %u, irq %d\n", hw
->regoff
, hw
->irq
);
341 spi_master_put(master
);
346 static const struct of_device_id altera_spi_match
[] = {
347 { .compatible
= "ALTR,spi-1.0", },
348 { .compatible
= "altr,spi-1.0", },
351 MODULE_DEVICE_TABLE(of
, altera_spi_match
);
352 #endif /* CONFIG_OF */
354 static const struct platform_device_id altera_spi_ids
[] = {
355 { DRV_NAME
, ALTERA_SPI_TYPE_UNKNOWN
},
356 { "subdev_spi_altera", ALTERA_SPI_TYPE_SUBDEV
},
359 MODULE_DEVICE_TABLE(platform
, altera_spi_ids
);
361 static struct platform_driver altera_spi_driver
= {
362 .probe
= altera_spi_probe
,
366 .of_match_table
= of_match_ptr(altera_spi_match
),
368 .id_table
= altera_spi_ids
,
370 module_platform_driver(altera_spi_driver
);
372 MODULE_DESCRIPTION("Altera SPI driver");
373 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
374 MODULE_LICENSE("GPL");
375 MODULE_ALIAS("platform:" DRV_NAME
);