Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.17 525 lines 13 kB view raw
1/* 2 * Freescale i.MX7ULP LPSPI driver 3 * 4 * Copyright 2016 Freescale Semiconductor, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 */ 17 18#include <linux/clk.h> 19#include <linux/completion.h> 20#include <linux/delay.h> 21#include <linux/err.h> 22#include <linux/interrupt.h> 23#include <linux/io.h> 24#include <linux/irq.h> 25#include <linux/kernel.h> 26#include <linux/module.h> 27#include <linux/of.h> 28#include <linux/of_device.h> 29#include <linux/platform_device.h> 30#include <linux/slab.h> 31#include <linux/spi/spi.h> 32#include <linux/spi/spi_bitbang.h> 33#include <linux/types.h> 34 35#define DRIVER_NAME "fsl_lpspi" 36 37/* i.MX7ULP LPSPI registers */ 38#define IMX7ULP_VERID 0x0 39#define IMX7ULP_PARAM 0x4 40#define IMX7ULP_CR 0x10 41#define IMX7ULP_SR 0x14 42#define IMX7ULP_IER 0x18 43#define IMX7ULP_DER 0x1c 44#define IMX7ULP_CFGR0 0x20 45#define IMX7ULP_CFGR1 0x24 46#define IMX7ULP_DMR0 0x30 47#define IMX7ULP_DMR1 0x34 48#define IMX7ULP_CCR 0x40 49#define IMX7ULP_FCR 0x58 50#define IMX7ULP_FSR 0x5c 51#define IMX7ULP_TCR 0x60 52#define IMX7ULP_TDR 0x64 53#define IMX7ULP_RSR 0x70 54#define IMX7ULP_RDR 0x74 55 56/* General control register field define */ 57#define CR_RRF BIT(9) 58#define CR_RTF BIT(8) 59#define CR_RST BIT(1) 60#define CR_MEN BIT(0) 61#define SR_TCF BIT(10) 62#define SR_RDF BIT(1) 63#define SR_TDF BIT(0) 64#define IER_TCIE BIT(10) 65#define IER_RDIE BIT(1) 66#define IER_TDIE BIT(0) 67#define CFGR1_PCSCFG BIT(27) 68#define CFGR1_PCSPOL BIT(8) 69#define CFGR1_NOSTALL BIT(3) 70#define CFGR1_MASTER BIT(0) 71#define RSR_RXEMPTY BIT(1) 72#define TCR_CPOL BIT(31) 73#define TCR_CPHA BIT(30) 74#define TCR_CONT BIT(21) 75#define TCR_CONTC BIT(20) 76#define TCR_RXMSK BIT(19) 77#define TCR_TXMSK BIT(18) 78 79static int clkdivs[] = {1, 2, 4, 8, 16, 32, 64, 128}; 80 81struct lpspi_config { 82 u8 bpw; 83 u8 chip_select; 84 u8 prescale; 85 u16 mode; 86 u32 speed_hz; 87}; 88 89struct fsl_lpspi_data { 90 struct device *dev; 91 void __iomem *base; 92 struct clk *clk; 93 94 void *rx_buf; 95 const void *tx_buf; 96 void (*tx)(struct fsl_lpspi_data *); 97 void (*rx)(struct fsl_lpspi_data *); 98 99 u32 remain; 100 u8 txfifosize; 101 u8 rxfifosize; 102 103 struct lpspi_config config; 104 struct completion xfer_done; 105}; 106 107static const struct of_device_id fsl_lpspi_dt_ids[] = { 108 { .compatible = "fsl,imx7ulp-spi", }, 109 { /* sentinel */ } 110}; 111MODULE_DEVICE_TABLE(of, fsl_lpspi_dt_ids); 112 113#define LPSPI_BUF_RX(type) \ 114static void fsl_lpspi_buf_rx_##type(struct fsl_lpspi_data *fsl_lpspi) \ 115{ \ 116 unsigned int val = readl(fsl_lpspi->base + IMX7ULP_RDR); \ 117 \ 118 if (fsl_lpspi->rx_buf) { \ 119 *(type *)fsl_lpspi->rx_buf = val; \ 120 fsl_lpspi->rx_buf += sizeof(type); \ 121 } \ 122} 123 124#define LPSPI_BUF_TX(type) \ 125static void fsl_lpspi_buf_tx_##type(struct fsl_lpspi_data *fsl_lpspi) \ 126{ \ 127 type val = 0; \ 128 \ 129 if (fsl_lpspi->tx_buf) { \ 130 val = *(type *)fsl_lpspi->tx_buf; \ 131 fsl_lpspi->tx_buf += sizeof(type); \ 132 } \ 133 \ 134 fsl_lpspi->remain -= sizeof(type); \ 135 writel(val, fsl_lpspi->base + IMX7ULP_TDR); \ 136} 137 138LPSPI_BUF_RX(u8) 139LPSPI_BUF_TX(u8) 140LPSPI_BUF_RX(u16) 141LPSPI_BUF_TX(u16) 142LPSPI_BUF_RX(u32) 143LPSPI_BUF_TX(u32) 144 145static void fsl_lpspi_intctrl(struct fsl_lpspi_data *fsl_lpspi, 146 unsigned int enable) 147{ 148 writel(enable, fsl_lpspi->base + IMX7ULP_IER); 149} 150 151static int lpspi_prepare_xfer_hardware(struct spi_master *master) 152{ 153 struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(master); 154 155 return clk_prepare_enable(fsl_lpspi->clk); 156} 157 158static int lpspi_unprepare_xfer_hardware(struct spi_master *master) 159{ 160 struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(master); 161 162 clk_disable_unprepare(fsl_lpspi->clk); 163 164 return 0; 165} 166 167static int fsl_lpspi_txfifo_empty(struct fsl_lpspi_data *fsl_lpspi) 168{ 169 u32 txcnt; 170 unsigned long orig_jiffies = jiffies; 171 172 do { 173 txcnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff; 174 175 if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { 176 dev_dbg(fsl_lpspi->dev, "txfifo empty timeout\n"); 177 return -ETIMEDOUT; 178 } 179 cond_resched(); 180 181 } while (txcnt); 182 183 return 0; 184} 185 186static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi) 187{ 188 u8 txfifo_cnt; 189 190 txfifo_cnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff; 191 192 while (txfifo_cnt < fsl_lpspi->txfifosize) { 193 if (!fsl_lpspi->remain) 194 break; 195 fsl_lpspi->tx(fsl_lpspi); 196 txfifo_cnt++; 197 } 198 199 if (!fsl_lpspi->remain && (txfifo_cnt < fsl_lpspi->txfifosize)) 200 writel(0, fsl_lpspi->base + IMX7ULP_TDR); 201 else 202 fsl_lpspi_intctrl(fsl_lpspi, IER_TDIE); 203} 204 205static void fsl_lpspi_read_rx_fifo(struct fsl_lpspi_data *fsl_lpspi) 206{ 207 while (!(readl(fsl_lpspi->base + IMX7ULP_RSR) & RSR_RXEMPTY)) 208 fsl_lpspi->rx(fsl_lpspi); 209} 210 211static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi, 212 bool is_first_xfer) 213{ 214 u32 temp = 0; 215 216 temp |= fsl_lpspi->config.bpw - 1; 217 temp |= fsl_lpspi->config.prescale << 27; 218 temp |= (fsl_lpspi->config.mode & 0x3) << 30; 219 temp |= (fsl_lpspi->config.chip_select & 0x3) << 24; 220 221 /* 222 * Set TCR_CONT will keep SS asserted after current transfer. 223 * For the first transfer, clear TCR_CONTC to assert SS. 224 * For subsequent transfer, set TCR_CONTC to keep SS asserted. 225 */ 226 temp |= TCR_CONT; 227 if (is_first_xfer) 228 temp &= ~TCR_CONTC; 229 else 230 temp |= TCR_CONTC; 231 232 writel(temp, fsl_lpspi->base + IMX7ULP_TCR); 233 234 dev_dbg(fsl_lpspi->dev, "TCR=0x%x\n", temp); 235} 236 237static void fsl_lpspi_set_watermark(struct fsl_lpspi_data *fsl_lpspi) 238{ 239 u32 temp; 240 241 temp = fsl_lpspi->txfifosize >> 1 | (fsl_lpspi->rxfifosize >> 1) << 16; 242 243 writel(temp, fsl_lpspi->base + IMX7ULP_FCR); 244 245 dev_dbg(fsl_lpspi->dev, "FCR=0x%x\n", temp); 246} 247 248static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) 249{ 250 struct lpspi_config config = fsl_lpspi->config; 251 unsigned int perclk_rate, scldiv; 252 u8 prescale; 253 254 perclk_rate = clk_get_rate(fsl_lpspi->clk); 255 for (prescale = 0; prescale < 8; prescale++) { 256 scldiv = perclk_rate / 257 (clkdivs[prescale] * config.speed_hz) - 2; 258 if (scldiv < 256) { 259 fsl_lpspi->config.prescale = prescale; 260 break; 261 } 262 } 263 264 if (prescale == 8 && scldiv >= 256) 265 return -EINVAL; 266 267 writel(scldiv, fsl_lpspi->base + IMX7ULP_CCR); 268 269 dev_dbg(fsl_lpspi->dev, "perclk=%d, speed=%d, prescale =%d, scldiv=%d\n", 270 perclk_rate, config.speed_hz, prescale, scldiv); 271 272 return 0; 273} 274 275static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi) 276{ 277 u32 temp; 278 int ret; 279 280 temp = CR_RST; 281 writel(temp, fsl_lpspi->base + IMX7ULP_CR); 282 writel(0, fsl_lpspi->base + IMX7ULP_CR); 283 284 ret = fsl_lpspi_set_bitrate(fsl_lpspi); 285 if (ret) 286 return ret; 287 288 fsl_lpspi_set_watermark(fsl_lpspi); 289 290 temp = CFGR1_PCSCFG | CFGR1_MASTER | CFGR1_NOSTALL; 291 if (fsl_lpspi->config.mode & SPI_CS_HIGH) 292 temp |= CFGR1_PCSPOL; 293 writel(temp, fsl_lpspi->base + IMX7ULP_CFGR1); 294 295 temp = readl(fsl_lpspi->base + IMX7ULP_CR); 296 temp |= CR_RRF | CR_RTF | CR_MEN; 297 writel(temp, fsl_lpspi->base + IMX7ULP_CR); 298 299 return 0; 300} 301 302static void fsl_lpspi_setup_transfer(struct spi_device *spi, 303 struct spi_transfer *t) 304{ 305 struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(spi->master); 306 307 fsl_lpspi->config.mode = spi->mode; 308 fsl_lpspi->config.bpw = t ? t->bits_per_word : spi->bits_per_word; 309 fsl_lpspi->config.speed_hz = t ? t->speed_hz : spi->max_speed_hz; 310 fsl_lpspi->config.chip_select = spi->chip_select; 311 312 if (!fsl_lpspi->config.speed_hz) 313 fsl_lpspi->config.speed_hz = spi->max_speed_hz; 314 if (!fsl_lpspi->config.bpw) 315 fsl_lpspi->config.bpw = spi->bits_per_word; 316 317 /* Initialize the functions for transfer */ 318 if (fsl_lpspi->config.bpw <= 8) { 319 fsl_lpspi->rx = fsl_lpspi_buf_rx_u8; 320 fsl_lpspi->tx = fsl_lpspi_buf_tx_u8; 321 } else if (fsl_lpspi->config.bpw <= 16) { 322 fsl_lpspi->rx = fsl_lpspi_buf_rx_u16; 323 fsl_lpspi->tx = fsl_lpspi_buf_tx_u16; 324 } else { 325 fsl_lpspi->rx = fsl_lpspi_buf_rx_u32; 326 fsl_lpspi->tx = fsl_lpspi_buf_tx_u32; 327 } 328 329 fsl_lpspi_config(fsl_lpspi); 330} 331 332static int fsl_lpspi_transfer_one(struct spi_master *master, 333 struct spi_device *spi, 334 struct spi_transfer *t) 335{ 336 struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(master); 337 int ret; 338 339 fsl_lpspi->tx_buf = t->tx_buf; 340 fsl_lpspi->rx_buf = t->rx_buf; 341 fsl_lpspi->remain = t->len; 342 343 reinit_completion(&fsl_lpspi->xfer_done); 344 fsl_lpspi_write_tx_fifo(fsl_lpspi); 345 346 ret = wait_for_completion_timeout(&fsl_lpspi->xfer_done, HZ); 347 if (!ret) { 348 dev_dbg(fsl_lpspi->dev, "wait for completion timeout\n"); 349 return -ETIMEDOUT; 350 } 351 352 ret = fsl_lpspi_txfifo_empty(fsl_lpspi); 353 if (ret) 354 return ret; 355 356 fsl_lpspi_read_rx_fifo(fsl_lpspi); 357 358 return 0; 359} 360 361static int fsl_lpspi_transfer_one_msg(struct spi_master *master, 362 struct spi_message *msg) 363{ 364 struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(master); 365 struct spi_device *spi = msg->spi; 366 struct spi_transfer *xfer; 367 bool is_first_xfer = true; 368 u32 temp; 369 int ret = 0; 370 371 msg->status = 0; 372 msg->actual_length = 0; 373 374 list_for_each_entry(xfer, &msg->transfers, transfer_list) { 375 fsl_lpspi_setup_transfer(spi, xfer); 376 fsl_lpspi_set_cmd(fsl_lpspi, is_first_xfer); 377 378 is_first_xfer = false; 379 380 ret = fsl_lpspi_transfer_one(master, spi, xfer); 381 if (ret < 0) 382 goto complete; 383 384 msg->actual_length += xfer->len; 385 } 386 387complete: 388 /* de-assert SS, then finalize current message */ 389 temp = readl(fsl_lpspi->base + IMX7ULP_TCR); 390 temp &= ~TCR_CONTC; 391 writel(temp, fsl_lpspi->base + IMX7ULP_TCR); 392 393 msg->status = ret; 394 spi_finalize_current_message(master); 395 396 return ret; 397} 398 399static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id) 400{ 401 struct fsl_lpspi_data *fsl_lpspi = dev_id; 402 u32 temp; 403 404 fsl_lpspi_intctrl(fsl_lpspi, 0); 405 temp = readl(fsl_lpspi->base + IMX7ULP_SR); 406 407 fsl_lpspi_read_rx_fifo(fsl_lpspi); 408 409 if (temp & SR_TDF) { 410 fsl_lpspi_write_tx_fifo(fsl_lpspi); 411 412 if (!fsl_lpspi->remain) 413 complete(&fsl_lpspi->xfer_done); 414 415 return IRQ_HANDLED; 416 } 417 418 return IRQ_NONE; 419} 420 421static int fsl_lpspi_probe(struct platform_device *pdev) 422{ 423 struct fsl_lpspi_data *fsl_lpspi; 424 struct spi_master *master; 425 struct resource *res; 426 int ret, irq; 427 u32 temp; 428 429 master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_lpspi_data)); 430 if (!master) 431 return -ENOMEM; 432 433 platform_set_drvdata(pdev, master); 434 435 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); 436 master->bus_num = pdev->id; 437 438 fsl_lpspi = spi_master_get_devdata(master); 439 fsl_lpspi->dev = &pdev->dev; 440 441 master->transfer_one_message = fsl_lpspi_transfer_one_msg; 442 master->prepare_transfer_hardware = lpspi_prepare_xfer_hardware; 443 master->unprepare_transfer_hardware = lpspi_unprepare_xfer_hardware; 444 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; 445 master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; 446 master->dev.of_node = pdev->dev.of_node; 447 master->bus_num = pdev->id; 448 449 init_completion(&fsl_lpspi->xfer_done); 450 451 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 452 fsl_lpspi->base = devm_ioremap_resource(&pdev->dev, res); 453 if (IS_ERR(fsl_lpspi->base)) { 454 ret = PTR_ERR(fsl_lpspi->base); 455 goto out_master_put; 456 } 457 458 irq = platform_get_irq(pdev, 0); 459 if (irq < 0) { 460 ret = irq; 461 goto out_master_put; 462 } 463 464 ret = devm_request_irq(&pdev->dev, irq, fsl_lpspi_isr, 0, 465 dev_name(&pdev->dev), fsl_lpspi); 466 if (ret) { 467 dev_err(&pdev->dev, "can't get irq%d: %d\n", irq, ret); 468 goto out_master_put; 469 } 470 471 fsl_lpspi->clk = devm_clk_get(&pdev->dev, "ipg"); 472 if (IS_ERR(fsl_lpspi->clk)) { 473 ret = PTR_ERR(fsl_lpspi->clk); 474 goto out_master_put; 475 } 476 477 ret = clk_prepare_enable(fsl_lpspi->clk); 478 if (ret) { 479 dev_err(&pdev->dev, "can't enable lpspi clock, ret=%d\n", ret); 480 goto out_master_put; 481 } 482 483 temp = readl(fsl_lpspi->base + IMX7ULP_PARAM); 484 fsl_lpspi->txfifosize = 1 << (temp & 0x0f); 485 fsl_lpspi->rxfifosize = 1 << ((temp >> 8) & 0x0f); 486 487 clk_disable_unprepare(fsl_lpspi->clk); 488 489 ret = devm_spi_register_master(&pdev->dev, master); 490 if (ret < 0) { 491 dev_err(&pdev->dev, "spi_register_master error.\n"); 492 goto out_master_put; 493 } 494 495 return 0; 496 497out_master_put: 498 spi_master_put(master); 499 500 return ret; 501} 502 503static int fsl_lpspi_remove(struct platform_device *pdev) 504{ 505 struct spi_master *master = platform_get_drvdata(pdev); 506 struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(master); 507 508 clk_disable_unprepare(fsl_lpspi->clk); 509 510 return 0; 511} 512 513static struct platform_driver fsl_lpspi_driver = { 514 .driver = { 515 .name = DRIVER_NAME, 516 .of_match_table = fsl_lpspi_dt_ids, 517 }, 518 .probe = fsl_lpspi_probe, 519 .remove = fsl_lpspi_remove, 520}; 521module_platform_driver(fsl_lpspi_driver); 522 523MODULE_DESCRIPTION("LPSPI Master Controller driver"); 524MODULE_AUTHOR("Gao Pan <pandy.gao@nxp.com>"); 525MODULE_LICENSE("GPL");