1010 * Ben Dooks <ben@simtec.co.uk>
1111 */
1212
13- #include <linux/interrupt.h>
1413#include <linux/errno.h>
1514#include <linux/module.h>
1615#include <linux/platform_device.h>
4140#define ALTERA_SPI_CONTROL_IE_MSK 0x100
4241#define ALTERA_SPI_CONTROL_SSO_MSK 0x400
4342
44- #define ALTERA_SPI_MAX_CS 32
45-
46- enum altera_spi_type {
47- ALTERA_SPI_TYPE_UNKNOWN ,
48- ALTERA_SPI_TYPE_SUBDEV ,
49- };
50-
51- struct altera_spi {
52- int irq ;
53- int len ;
54- int count ;
55- int bytes_per_word ;
56- u32 imr ;
57-
58- /* data buffers */
59- const unsigned char * tx ;
60- unsigned char * rx ;
61-
62- struct regmap * regmap ;
63- u32 regoff ;
64- struct device * dev ;
65- };
66-
67- static const struct regmap_config spi_altera_config = {
68- .reg_bits = 32 ,
69- .reg_stride = 4 ,
70- .val_bits = 32 ,
71- .fast_io = true,
72- };
73-
7443static int altr_spi_writel (struct altera_spi * hw , unsigned int reg ,
7544 unsigned int val )
7645{
@@ -211,7 +180,7 @@ static int altera_spi_txrx(struct spi_master *master,
211180 return 0 ;
212181}
213182
214- static irqreturn_t altera_spi_irq (int irq , void * dev )
183+ irqreturn_t altera_spi_irq (int irq , void * dev )
215184{
216185 struct spi_master * master = dev ;
217186 struct altera_spi * hw = spi_master_get_devdata (master );
@@ -230,149 +199,24 @@ static irqreturn_t altera_spi_irq(int irq, void *dev)
230199
231200 return IRQ_HANDLED ;
232201}
202+ EXPORT_SYMBOL_GPL (altera_spi_irq );
233203
234- static int altera_spi_probe (struct platform_device * pdev )
204+ void altera_spi_init_master (struct spi_master * master )
235205{
236- const struct platform_device_id * platid = platform_get_device_id (pdev );
237- struct altera_spi_platform_data * pdata = dev_get_platdata (& pdev -> dev );
238- enum altera_spi_type type = ALTERA_SPI_TYPE_UNKNOWN ;
239- struct altera_spi * hw ;
240- struct spi_master * master ;
241- int err = - ENODEV ;
206+ struct altera_spi * hw = spi_master_get_devdata (master );
242207 u32 val ;
243- u16 i ;
244-
245- master = spi_alloc_master (& pdev -> dev , sizeof (struct altera_spi ));
246- if (!master )
247- return err ;
248-
249- /* setup the master state. */
250- master -> bus_num = pdev -> id ;
251-
252- if (pdata ) {
253- if (pdata -> num_chipselect > ALTERA_SPI_MAX_CS ) {
254- dev_err (& pdev -> dev ,
255- "Invalid number of chipselect: %hu\n" ,
256- pdata -> num_chipselect );
257- err = - EINVAL ;
258- goto exit ;
259- }
260208
261- master -> num_chipselect = pdata -> num_chipselect ;
262- master -> mode_bits = pdata -> mode_bits ;
263- master -> bits_per_word_mask = pdata -> bits_per_word_mask ;
264- } else {
265- master -> num_chipselect = 16 ;
266- master -> mode_bits = SPI_CS_HIGH ;
267- master -> bits_per_word_mask = SPI_BPW_RANGE_MASK (1 , 16 );
268- }
269-
270- master -> dev .of_node = pdev -> dev .of_node ;
271209 master -> transfer_one = altera_spi_txrx ;
272210 master -> set_cs = altera_spi_set_cs ;
273211
274- hw = spi_master_get_devdata (master );
275- hw -> dev = & pdev -> dev ;
276-
277- if (platid )
278- type = platid -> driver_data ;
279-
280- /* find and map our resources */
281- if (type == ALTERA_SPI_TYPE_SUBDEV ) {
282- struct resource * regoff ;
283-
284- hw -> regmap = dev_get_regmap (pdev -> dev .parent , NULL );
285- if (!hw -> regmap ) {
286- dev_err (& pdev -> dev , "get regmap failed\n" );
287- goto exit ;
288- }
289-
290- regoff = platform_get_resource (pdev , IORESOURCE_REG , 0 );
291- if (regoff )
292- hw -> regoff = regoff -> start ;
293- } else {
294- void __iomem * res ;
295-
296- res = devm_platform_ioremap_resource (pdev , 0 );
297- if (IS_ERR (res )) {
298- err = PTR_ERR (res );
299- goto exit ;
300- }
301-
302- hw -> regmap = devm_regmap_init_mmio (& pdev -> dev , res ,
303- & spi_altera_config );
304- if (IS_ERR (hw -> regmap )) {
305- dev_err (& pdev -> dev , "regmap mmio init failed\n" );
306- err = PTR_ERR (hw -> regmap );
307- goto exit ;
308- }
309- }
310-
311212 /* program defaults into the registers */
312213 hw -> imr = 0 ; /* disable spi interrupts */
313214 altr_spi_writel (hw , ALTERA_SPI_CONTROL , hw -> imr );
314215 altr_spi_writel (hw , ALTERA_SPI_STATUS , 0 ); /* clear status reg */
315216 altr_spi_readl (hw , ALTERA_SPI_STATUS , & val );
316217 if (val & ALTERA_SPI_STATUS_RRDY_MSK )
317218 altr_spi_readl (hw , ALTERA_SPI_RXDATA , & val ); /* flush rxdata */
318- /* irq is optional */
319- hw -> irq = platform_get_irq (pdev , 0 );
320- if (hw -> irq >= 0 ) {
321- err = devm_request_irq (& pdev -> dev , hw -> irq , altera_spi_irq , 0 ,
322- pdev -> name , master );
323- if (err )
324- goto exit ;
325- }
326-
327- err = devm_spi_register_master (& pdev -> dev , master );
328- if (err )
329- goto exit ;
330-
331- if (pdata ) {
332- for (i = 0 ; i < pdata -> num_devices ; i ++ ) {
333- if (!spi_new_device (master , pdata -> devices + i ))
334- dev_warn (& pdev -> dev ,
335- "unable to create SPI device: %s\n" ,
336- pdata -> devices [i ].modalias );
337- }
338- }
339-
340- dev_info (& pdev -> dev , "regoff %u, irq %d\n" , hw -> regoff , hw -> irq );
341-
342- return 0 ;
343- exit :
344- spi_master_put (master );
345- return err ;
346219}
220+ EXPORT_SYMBOL_GPL (altera_spi_init_master );
347221
348- #ifdef CONFIG_OF
349- static const struct of_device_id altera_spi_match [] = {
350- { .compatible = "ALTR,spi-1.0" , },
351- { .compatible = "altr,spi-1.0" , },
352- {},
353- };
354- MODULE_DEVICE_TABLE (of , altera_spi_match );
355- #endif /* CONFIG_OF */
356-
357- static const struct platform_device_id altera_spi_ids [] = {
358- { DRV_NAME , ALTERA_SPI_TYPE_UNKNOWN },
359- { "subdev_spi_altera" , ALTERA_SPI_TYPE_SUBDEV },
360- { }
361- };
362- MODULE_DEVICE_TABLE (platform , altera_spi_ids );
363-
364- static struct platform_driver altera_spi_driver = {
365- .probe = altera_spi_probe ,
366- .driver = {
367- .name = DRV_NAME ,
368- .pm = NULL ,
369- .of_match_table = of_match_ptr (altera_spi_match ),
370- },
371- .id_table = altera_spi_ids ,
372- };
373- module_platform_driver (altera_spi_driver );
374-
375- MODULE_DESCRIPTION ("Altera SPI driver" );
376- MODULE_AUTHOR ("Thomas Chou <thomas@wytron.com.tw>" );
377222MODULE_LICENSE ("GPL" );
378- MODULE_ALIAS ("platform:" DRV_NAME );
0 commit comments