aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-clps711x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-clps711x.c')
-rw-r--r--drivers/spi/spi-clps711x.c227
1 files changed, 107 insertions, 120 deletions
diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c
index 374ba4a48a9e..4cd62f636547 100644
--- a/drivers/spi/spi-clps711x.c
+++ b/drivers/spi/spi-clps711x.c
@@ -11,158 +11,125 @@
11 11
12#include <linux/io.h> 12#include <linux/io.h>
13#include <linux/clk.h> 13#include <linux/clk.h>
14#include <linux/init.h>
15#include <linux/gpio.h> 14#include <linux/gpio.h>
16#include <linux/delay.h> 15#include <linux/delay.h>
17#include <linux/module.h> 16#include <linux/module.h>
18#include <linux/interrupt.h> 17#include <linux/interrupt.h>
19#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/regmap.h>
20#include <linux/mfd/syscon.h>
21#include <linux/mfd/syscon/clps711x.h>
20#include <linux/spi/spi.h> 22#include <linux/spi/spi.h>
21#include <linux/platform_data/spi-clps711x.h> 23#include <linux/platform_data/spi-clps711x.h>
22 24
23#include <mach/hardware.h>
24
25#define DRIVER_NAME "spi-clps711x" 25#define DRIVER_NAME "spi-clps711x"
26 26
27struct spi_clps711x_data { 27#define SYNCIO_FRMLEN(x) ((x) << 8)
28 struct completion done; 28#define SYNCIO_TXFRMEN (1 << 14)
29 29
30struct spi_clps711x_data {
31 void __iomem *syncio;
32 struct regmap *syscon;
33 struct regmap *syscon1;
30 struct clk *spi_clk; 34 struct clk *spi_clk;
31 u32 max_speed_hz;
32 35
33 u8 *tx_buf; 36 u8 *tx_buf;
34 u8 *rx_buf; 37 u8 *rx_buf;
35 int count; 38 unsigned int bpw;
36 int len; 39 int len;
37
38 int chipselect[0];
39}; 40};
40 41
41static int spi_clps711x_setup(struct spi_device *spi) 42static int spi_clps711x_setup(struct spi_device *spi)
42{ 43{
43 struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master);
44
45 /* We are expect that SPI-device is not selected */ 44 /* We are expect that SPI-device is not selected */
46 gpio_direction_output(hw->chipselect[spi->chip_select], 45 gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
47 !(spi->mode & SPI_CS_HIGH));
48 46
49 return 0; 47 return 0;
50} 48}
51 49
52static void spi_clps711x_setup_mode(struct spi_device *spi) 50static void spi_clps711x_setup_xfer(struct spi_device *spi,
53{ 51 struct spi_transfer *xfer)
54 /* Setup edge for transfer */
55 if (spi->mode & SPI_CPHA)
56 clps_writew(clps_readw(SYSCON3) | SYSCON3_ADCCKNSEN, SYSCON3);
57 else
58 clps_writew(clps_readw(SYSCON3) & ~SYSCON3_ADCCKNSEN, SYSCON3);
59}
60
61static int spi_clps711x_setup_xfer(struct spi_device *spi,
62 struct spi_transfer *xfer)
63{ 52{
64 u32 speed = xfer->speed_hz ? : spi->max_speed_hz; 53 struct spi_master *master = spi->master;
65 u8 bpw = xfer->bits_per_word; 54 struct spi_clps711x_data *hw = spi_master_get_devdata(master);
66 struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master);
67
68 if (bpw != 8) {
69 dev_err(&spi->dev, "Unsupported master bus width %i\n", bpw);
70 return -EINVAL;
71 }
72 55
73 /* Setup SPI frequency divider */ 56 /* Setup SPI frequency divider */
74 if (!speed || (speed >= hw->max_speed_hz)) 57 if (xfer->speed_hz >= master->max_speed_hz)
75 clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) | 58 regmap_update_bits(hw->syscon1, SYSCON_OFFSET,
76 SYSCON1_ADCKSEL(3), SYSCON1); 59 SYSCON1_ADCKSEL_MASK, SYSCON1_ADCKSEL(3));
77 else if (speed >= (hw->max_speed_hz / 2)) 60 else if (xfer->speed_hz >= (master->max_speed_hz / 2))
78 clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) | 61 regmap_update_bits(hw->syscon1, SYSCON_OFFSET,
79 SYSCON1_ADCKSEL(2), SYSCON1); 62 SYSCON1_ADCKSEL_MASK, SYSCON1_ADCKSEL(2));
80 else if (speed >= (hw->max_speed_hz / 8)) 63 else if (xfer->speed_hz >= (master->max_speed_hz / 8))
81 clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) | 64 regmap_update_bits(hw->syscon1, SYSCON_OFFSET,
82 SYSCON1_ADCKSEL(1), SYSCON1); 65 SYSCON1_ADCKSEL_MASK, SYSCON1_ADCKSEL(1));
83 else 66 else
84 clps_writel((clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK) | 67 regmap_update_bits(hw->syscon1, SYSCON_OFFSET,
85 SYSCON1_ADCKSEL(0), SYSCON1); 68 SYSCON1_ADCKSEL_MASK, SYSCON1_ADCKSEL(0));
86
87 return 0;
88} 69}
89 70
90static int spi_clps711x_transfer_one_message(struct spi_master *master, 71static int spi_clps711x_prepare_message(struct spi_master *master,
91 struct spi_message *msg) 72 struct spi_message *msg)
92{ 73{
93 struct spi_clps711x_data *hw = spi_master_get_devdata(master); 74 struct spi_clps711x_data *hw = spi_master_get_devdata(master);
94 struct spi_transfer *xfer; 75 struct spi_device *spi = msg->spi;
95 int status = 0, cs = hw->chipselect[msg->spi->chip_select];
96 u32 data;
97
98 spi_clps711x_setup_mode(msg->spi);
99
100 list_for_each_entry(xfer, &msg->transfers, transfer_list) {
101 if (spi_clps711x_setup_xfer(msg->spi, xfer)) {
102 status = -EINVAL;
103 goto out_xfr;
104 }
105 76
106 gpio_set_value(cs, !!(msg->spi->mode & SPI_CS_HIGH)); 77 /* Setup mode for transfer */
107 78 return regmap_update_bits(hw->syscon, SYSCON_OFFSET, SYSCON3_ADCCKNSEN,
108 reinit_completion(&hw->done); 79 (spi->mode & SPI_CPHA) ?
109 80 SYSCON3_ADCCKNSEN : 0);
110 hw->count = 0; 81}
111 hw->len = xfer->len;
112 hw->tx_buf = (u8 *)xfer->tx_buf;
113 hw->rx_buf = (u8 *)xfer->rx_buf;
114
115 /* Initiate transfer */
116 data = hw->tx_buf ? hw->tx_buf[hw->count] : 0;
117 clps_writel(data | SYNCIO_FRMLEN(8) | SYNCIO_TXFRMEN, SYNCIO);
118
119 wait_for_completion(&hw->done);
120 82
121 if (xfer->delay_usecs) 83static int spi_clps711x_transfer_one(struct spi_master *master,
122 udelay(xfer->delay_usecs); 84 struct spi_device *spi,
85 struct spi_transfer *xfer)
86{
87 struct spi_clps711x_data *hw = spi_master_get_devdata(master);
88 u8 data;
123 89
124 if (xfer->cs_change || 90 spi_clps711x_setup_xfer(spi, xfer);
125 list_is_last(&xfer->transfer_list, &msg->transfers))
126 gpio_set_value(cs, !(msg->spi->mode & SPI_CS_HIGH));
127 91
128 msg->actual_length += xfer->len; 92 hw->len = xfer->len;
129 } 93 hw->bpw = xfer->bits_per_word;
94 hw->tx_buf = (u8 *)xfer->tx_buf;
95 hw->rx_buf = (u8 *)xfer->rx_buf;
130 96
131out_xfr: 97 /* Initiate transfer */
132 msg->status = status; 98 data = hw->tx_buf ? *hw->tx_buf++ : 0;
133 spi_finalize_current_message(master); 99 writel(data | SYNCIO_FRMLEN(hw->bpw) | SYNCIO_TXFRMEN, hw->syncio);
134 100
135 return 0; 101 return 1;
136} 102}
137 103
138static irqreturn_t spi_clps711x_isr(int irq, void *dev_id) 104static irqreturn_t spi_clps711x_isr(int irq, void *dev_id)
139{ 105{
140 struct spi_clps711x_data *hw = (struct spi_clps711x_data *)dev_id; 106 struct spi_master *master = dev_id;
141 u32 data; 107 struct spi_clps711x_data *hw = spi_master_get_devdata(master);
108 u8 data;
142 109
143 /* Handle RX */ 110 /* Handle RX */
144 data = clps_readb(SYNCIO); 111 data = readb(hw->syncio);
145 if (hw->rx_buf) 112 if (hw->rx_buf)
146 hw->rx_buf[hw->count] = (u8)data; 113 *hw->rx_buf++ = data;
147
148 hw->count++;
149 114
150 /* Handle TX */ 115 /* Handle TX */
151 if (hw->count < hw->len) { 116 if (--hw->len > 0) {
152 data = hw->tx_buf ? hw->tx_buf[hw->count] : 0; 117 data = hw->tx_buf ? *hw->tx_buf++ : 0;
153 clps_writel(data | SYNCIO_FRMLEN(8) | SYNCIO_TXFRMEN, SYNCIO); 118 writel(data | SYNCIO_FRMLEN(hw->bpw) | SYNCIO_TXFRMEN,
119 hw->syncio);
154 } else 120 } else
155 complete(&hw->done); 121 spi_finalize_current_transfer(master);
156 122
157 return IRQ_HANDLED; 123 return IRQ_HANDLED;
158} 124}
159 125
160static int spi_clps711x_probe(struct platform_device *pdev) 126static int spi_clps711x_probe(struct platform_device *pdev)
161{ 127{
162 int i, ret;
163 struct spi_master *master;
164 struct spi_clps711x_data *hw; 128 struct spi_clps711x_data *hw;
165 struct spi_clps711x_pdata *pdata = dev_get_platdata(&pdev->dev); 129 struct spi_clps711x_pdata *pdata = dev_get_platdata(&pdev->dev);
130 struct spi_master *master;
131 struct resource *res;
132 int i, irq, ret;
166 133
167 if (!pdata) { 134 if (!pdata) {
168 dev_err(&pdev->dev, "No platform data supplied\n"); 135 dev_err(&pdev->dev, "No platform data supplied\n");
@@ -174,33 +141,37 @@ static int spi_clps711x_probe(struct platform_device *pdev)
174 return -EINVAL; 141 return -EINVAL;
175 } 142 }
176 143
177 master = spi_alloc_master(&pdev->dev, 144 irq = platform_get_irq(pdev, 0);
178 sizeof(struct spi_clps711x_data) + 145 if (irq < 0)
179 sizeof(int) * pdata->num_chipselect); 146 return irq;
180 if (!master) { 147
181 dev_err(&pdev->dev, "SPI allocating memory error\n"); 148 master = spi_alloc_master(&pdev->dev, sizeof(*hw));
149 if (!master)
182 return -ENOMEM; 150 return -ENOMEM;
151
152 master->cs_gpios = devm_kzalloc(&pdev->dev, sizeof(int) *
153 pdata->num_chipselect, GFP_KERNEL);
154 if (!master->cs_gpios) {
155 ret = -ENOMEM;
156 goto err_out;
183 } 157 }
184 158
185 master->bus_num = pdev->id; 159 master->bus_num = pdev->id;
186 master->mode_bits = SPI_CPHA | SPI_CS_HIGH; 160 master->mode_bits = SPI_CPHA | SPI_CS_HIGH;
187 master->bits_per_word_mask = SPI_BPW_MASK(8); 161 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8);
188 master->num_chipselect = pdata->num_chipselect; 162 master->num_chipselect = pdata->num_chipselect;
189 master->setup = spi_clps711x_setup; 163 master->setup = spi_clps711x_setup;
190 master->transfer_one_message = spi_clps711x_transfer_one_message; 164 master->prepare_message = spi_clps711x_prepare_message;
165 master->transfer_one = spi_clps711x_transfer_one;
191 166
192 hw = spi_master_get_devdata(master); 167 hw = spi_master_get_devdata(master);
193 168
194 for (i = 0; i < master->num_chipselect; i++) { 169 for (i = 0; i < master->num_chipselect; i++) {
195 hw->chipselect[i] = pdata->chipselect[i]; 170 master->cs_gpios[i] = pdata->chipselect[i];
196 if (!gpio_is_valid(hw->chipselect[i])) { 171 ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i],
197 dev_err(&pdev->dev, "Invalid CS GPIO %i\n", i); 172 DRIVER_NAME);
198 ret = -EINVAL; 173 if (ret) {
199 goto err_out;
200 }
201 if (devm_gpio_request(&pdev->dev, hw->chipselect[i], NULL)) {
202 dev_err(&pdev->dev, "Can't get CS GPIO %i\n", i); 174 dev_err(&pdev->dev, "Can't get CS GPIO %i\n", i);
203 ret = -EINVAL;
204 goto err_out; 175 goto err_out;
205 } 176 }
206 } 177 }
@@ -211,29 +182,45 @@ static int spi_clps711x_probe(struct platform_device *pdev)
211 ret = PTR_ERR(hw->spi_clk); 182 ret = PTR_ERR(hw->spi_clk);
212 goto err_out; 183 goto err_out;
213 } 184 }
214 hw->max_speed_hz = clk_get_rate(hw->spi_clk); 185 master->max_speed_hz = clk_get_rate(hw->spi_clk);
215 186
216 init_completion(&hw->done);
217 platform_set_drvdata(pdev, master); 187 platform_set_drvdata(pdev, master);
218 188
189 hw->syscon = syscon_regmap_lookup_by_pdevname("syscon.3");
190 if (IS_ERR(hw->syscon)) {
191 ret = PTR_ERR(hw->syscon);
192 goto err_out;
193 }
194
195 hw->syscon1 = syscon_regmap_lookup_by_pdevname("syscon.1");
196 if (IS_ERR(hw->syscon1)) {
197 ret = PTR_ERR(hw->syscon1);
198 goto err_out;
199 }
200
201 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
202 hw->syncio = devm_ioremap_resource(&pdev->dev, res);
203 if (IS_ERR(hw->syncio)) {
204 ret = PTR_ERR(hw->syncio);
205 goto err_out;
206 }
207
219 /* Disable extended mode due hardware problems */ 208 /* Disable extended mode due hardware problems */
220 clps_writew(clps_readw(SYSCON3) & ~SYSCON3_ADCCON, SYSCON3); 209 regmap_update_bits(hw->syscon, SYSCON_OFFSET, SYSCON3_ADCCON, 0);
221 210
222 /* Clear possible pending interrupt */ 211 /* Clear possible pending interrupt */
223 clps_readl(SYNCIO); 212 readl(hw->syncio);
224 213
225 ret = devm_request_irq(&pdev->dev, IRQ_SSEOTI, spi_clps711x_isr, 0, 214 ret = devm_request_irq(&pdev->dev, irq, spi_clps711x_isr, 0,
226 dev_name(&pdev->dev), hw); 215 dev_name(&pdev->dev), master);
227 if (ret) { 216 if (ret)
228 dev_err(&pdev->dev, "Can't request IRQ\n");
229 goto err_out; 217 goto err_out;
230 }
231 218
232 ret = devm_spi_register_master(&pdev->dev, master); 219 ret = devm_spi_register_master(&pdev->dev, master);
233 if (!ret) { 220 if (!ret) {
234 dev_info(&pdev->dev, 221 dev_info(&pdev->dev,
235 "SPI bus driver initialized. Master clock %u Hz\n", 222 "SPI bus driver initialized. Master clock %u Hz\n",
236 hw->max_speed_hz); 223 master->max_speed_hz);
237 return 0; 224 return 0;
238 } 225 }
239 226