Blame view

drivers/spi/spi-dw-mmio.c 3.17 KB
f7b6fd6d1   Jean-Hugues Deschenes   Memory-mapped dw_...
1
  /*
ca632f556   Grant Likely   spi: reorganize d...
2
   * Memory-mapped interface driver for DW SPI Core
f7b6fd6d1   Jean-Hugues Deschenes   Memory-mapped dw_...
3
4
5
6
7
8
9
10
11
   *
   * Copyright (c) 2010, Octasic semiconductor.
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms and conditions of the GNU General Public License,
   * version 2, as published by the Free Software Foundation.
   */
  
  #include <linux/clk.h>
50c01fc35   Jamie Iles   spi/dw_spi: don't...
12
  #include <linux/err.h>
f7b6fd6d1   Jean-Hugues Deschenes   Memory-mapped dw_...
13
14
  #include <linux/interrupt.h>
  #include <linux/platform_device.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
15
  #include <linux/slab.h>
f7b6fd6d1   Jean-Hugues Deschenes   Memory-mapped dw_...
16
  #include <linux/spi/spi.h>
568a60eda   Grant Likely   spi/dw_spi: move ...
17
  #include <linux/scatterlist.h>
d7614de42   Paul Gortmaker   spi: Add module.h...
18
  #include <linux/module.h>
568a60eda   Grant Likely   spi/dw_spi: move ...
19

ca632f556   Grant Likely   spi: reorganize d...
20
  #include "spi-dw.h"
f7b6fd6d1   Jean-Hugues Deschenes   Memory-mapped dw_...
21
22
23
24
  
  #define DRIVER_NAME "dw_spi_mmio"
  
  struct dw_spi_mmio {
0a4c1d7d4   Jean-Hugues Deschenes   spi/dw_spi: mmio ...
25
26
  	struct dw_spi  dws;
  	struct clk     *clk;
f7b6fd6d1   Jean-Hugues Deschenes   Memory-mapped dw_...
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  };
  
  static int __devinit dw_spi_mmio_probe(struct platform_device *pdev)
  {
  	struct dw_spi_mmio *dwsmmio;
  	struct dw_spi *dws;
  	struct resource *mem, *ioarea;
  	int ret;
  
  	dwsmmio = kzalloc(sizeof(struct dw_spi_mmio), GFP_KERNEL);
  	if (!dwsmmio) {
  		ret = -ENOMEM;
  		goto err_end;
  	}
  
  	dws = &dwsmmio->dws;
  
  	/* Get basic io resource and map it */
  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	if (!mem) {
  		dev_err(&pdev->dev, "no mem resource?
  ");
  		ret = -EINVAL;
  		goto err_kfree;
  	}
  
  	ioarea = request_mem_region(mem->start, resource_size(mem),
  			pdev->name);
  	if (!ioarea) {
  		dev_err(&pdev->dev, "SPI region already claimed
  ");
  		ret = -EBUSY;
  		goto err_kfree;
  	}
  
  	dws->regs = ioremap_nocache(mem->start, resource_size(mem));
  	if (!dws->regs) {
  		dev_err(&pdev->dev, "SPI region already mapped
  ");
  		ret = -ENOMEM;
  		goto err_release_reg;
  	}
  
  	dws->irq = platform_get_irq(pdev, 0);
  	if (dws->irq < 0) {
  		dev_err(&pdev->dev, "no irq resource?
  ");
  		ret = dws->irq; /* -ENXIO */
  		goto err_unmap;
  	}
  
  	dwsmmio->clk = clk_get(&pdev->dev, NULL);
50c01fc35   Jamie Iles   spi/dw_spi: don't...
79
80
  	if (IS_ERR(dwsmmio->clk)) {
  		ret = PTR_ERR(dwsmmio->clk);
f7b6fd6d1   Jean-Hugues Deschenes   Memory-mapped dw_...
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  		goto err_irq;
  	}
  	clk_enable(dwsmmio->clk);
  
  	dws->parent_dev = &pdev->dev;
  	dws->bus_num = 0;
  	dws->num_cs = 4;
  	dws->max_freq = clk_get_rate(dwsmmio->clk);
  
  	ret = dw_spi_add_host(dws);
  	if (ret)
  		goto err_clk;
  
  	platform_set_drvdata(pdev, dwsmmio);
  	return 0;
  
  err_clk:
  	clk_disable(dwsmmio->clk);
  	clk_put(dwsmmio->clk);
  	dwsmmio->clk = NULL;
  err_irq:
  	free_irq(dws->irq, dws);
  err_unmap:
  	iounmap(dws->regs);
  err_release_reg:
  	release_mem_region(mem->start, resource_size(mem));
  err_kfree:
  	kfree(dwsmmio);
  err_end:
  	return ret;
  }
  
  static int __devexit dw_spi_mmio_remove(struct platform_device *pdev)
  {
  	struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev);
  	struct resource *mem;
  
  	platform_set_drvdata(pdev, NULL);
  
  	clk_disable(dwsmmio->clk);
  	clk_put(dwsmmio->clk);
  	dwsmmio->clk = NULL;
  
  	free_irq(dwsmmio->dws.irq, &dwsmmio->dws);
  	dw_spi_remove_host(&dwsmmio->dws);
  	iounmap(dwsmmio->dws.regs);
  	kfree(dwsmmio);
  
  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	release_mem_region(mem->start, resource_size(mem));
  	return 0;
  }
  
  static struct platform_driver dw_spi_mmio_driver = {
940ab8896   Grant Likely   drivercore: Add h...
135
  	.probe		= dw_spi_mmio_probe,
f7b6fd6d1   Jean-Hugues Deschenes   Memory-mapped dw_...
136
137
138
139
140
141
  	.remove		= __devexit_p(dw_spi_mmio_remove),
  	.driver		= {
  		.name	= DRIVER_NAME,
  		.owner	= THIS_MODULE,
  	},
  };
940ab8896   Grant Likely   drivercore: Add h...
142
  module_platform_driver(dw_spi_mmio_driver);
f7b6fd6d1   Jean-Hugues Deschenes   Memory-mapped dw_...
143
144
145
146
  
  MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>");
  MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core");
  MODULE_LICENSE("GPL v2");