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.

spi: spi_amd: Add support for SPI MEM framework

Add support to the SPI controller driver to use SPI MEM framework.
SPI subsystem utilizing the SPI memory operations allows to re-use
SPI controller drivers for both SPI NOR devices, regular SPI devices
as well as SPI NAND devices.

Add below functions of spi_mem_ops to support SPI MEM framework
- exec-op(): to execute the memory operations.
- supports_op(): to check if the memory operation is supported.
- adjust_op_size(): to split data transfers so that they don’t exceed the
max transfer size supported by the controller.

Suggested-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
Co-developed-by: Krishnamoorthi M <krishnamoorthi.m@amd.com>
Signed-off-by: Krishnamoorthi M <krishnamoorthi.m@amd.com>
Co-developed-by: Akshata MukundShetty <akshata.mukundshetty@amd.com>
Signed-off-by: Akshata MukundShetty <akshata.mukundshetty@amd.com>
Signed-off-by: Raju Rangoju <Raju.Rangoju@amd.com>
Link: https://msgid.link/r/20240229134544.3461757-1-Raju.Rangoju@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Raju Rangoju and committed by
Mark Brown
6defadbe bdeef5dc

+112
+112
drivers/spi/spi-amd.c
··· 13 13 #include <linux/delay.h> 14 14 #include <linux/spi/spi.h> 15 15 #include <linux/iopoll.h> 16 + #include <linux/spi/spi-mem.h> 16 17 17 18 #define AMD_SPI_CTRL0_REG 0x00 18 19 #define AMD_SPI_EXEC_CMD BIT(16) ··· 36 35 37 36 #define AMD_SPI_FIFO_SIZE 70 38 37 #define AMD_SPI_MEM_SIZE 200 38 + #define AMD_SPI_MAX_DATA 64 39 39 40 40 #define AMD_SPI_ENA_REG 0x20 41 41 #define AMD_SPI_ALT_SPD_SHIFT 20 ··· 360 358 return message->status; 361 359 } 362 360 361 + static bool amd_spi_supports_op(struct spi_mem *mem, 362 + const struct spi_mem_op *op) 363 + { 364 + /* bus width is number of IO lines used to transmit */ 365 + if (op->cmd.buswidth > 1 || op->addr.buswidth > 1 || 366 + op->data.buswidth > 1 || op->data.nbytes > AMD_SPI_MAX_DATA) 367 + return false; 368 + 369 + return spi_mem_default_supports_op(mem, op); 370 + } 371 + 372 + static int amd_spi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) 373 + { 374 + op->data.nbytes = clamp_val(op->data.nbytes, 0, AMD_SPI_MAX_DATA); 375 + return 0; 376 + } 377 + 378 + static void amd_spi_set_addr(struct amd_spi *amd_spi, 379 + const struct spi_mem_op *op) 380 + { 381 + u8 nbytes = op->addr.nbytes; 382 + u64 addr_val = op->addr.val; 383 + int base_addr, i; 384 + 385 + base_addr = AMD_SPI_FIFO_BASE + nbytes; 386 + 387 + for (i = 0; i < nbytes; i++) { 388 + amd_spi_writereg8(amd_spi, base_addr - i - 1, addr_val & 389 + GENMASK(7, 0)); 390 + addr_val >>= 8; 391 + } 392 + } 393 + 394 + static void amd_spi_mem_data_out(struct amd_spi *amd_spi, 395 + const struct spi_mem_op *op) 396 + { 397 + int base_addr = AMD_SPI_FIFO_BASE + op->addr.nbytes; 398 + u8 *buf = (u8 *)op->data.buf.out; 399 + u32 nbytes = op->data.nbytes; 400 + int i; 401 + 402 + amd_spi_set_opcode(amd_spi, op->cmd.opcode); 403 + amd_spi_set_addr(amd_spi, op); 404 + 405 + for (i = 0; i < nbytes; i++) 406 + amd_spi_writereg8(amd_spi, (base_addr + i), buf[i]); 407 + 408 + amd_spi_set_tx_count(amd_spi, op->addr.nbytes + op->data.nbytes); 409 + amd_spi_set_rx_count(amd_spi, 0); 410 + amd_spi_clear_fifo_ptr(amd_spi); 411 + amd_spi_execute_opcode(amd_spi); 412 + } 413 + 414 + static void amd_spi_mem_data_in(struct amd_spi *amd_spi, 415 + const struct spi_mem_op *op) 416 + { 417 + int offset = (op->addr.nbytes == 0) ? 0 : 1; 418 + u8 *buf = (u8 *)op->data.buf.in; 419 + u32 nbytes = op->data.nbytes; 420 + int base_addr, i; 421 + 422 + base_addr = AMD_SPI_FIFO_BASE + op->addr.nbytes + offset; 423 + 424 + amd_spi_set_opcode(amd_spi, op->cmd.opcode); 425 + amd_spi_set_addr(amd_spi, op); 426 + amd_spi_set_tx_count(amd_spi, op->addr.nbytes); 427 + amd_spi_set_rx_count(amd_spi, op->data.nbytes + 1); 428 + amd_spi_clear_fifo_ptr(amd_spi); 429 + amd_spi_execute_opcode(amd_spi); 430 + amd_spi_busy_wait(amd_spi); 431 + 432 + for (i = 0; i < nbytes; i++) 433 + buf[i] = amd_spi_readreg8(amd_spi, base_addr + i); 434 + } 435 + 436 + static int amd_spi_exec_mem_op(struct spi_mem *mem, 437 + const struct spi_mem_op *op) 438 + { 439 + struct amd_spi *amd_spi; 440 + int ret; 441 + 442 + amd_spi = spi_controller_get_devdata(mem->spi->controller); 443 + 444 + ret = amd_set_spi_freq(amd_spi, mem->spi->max_speed_hz); 445 + if (ret) 446 + return ret; 447 + 448 + switch (op->data.dir) { 449 + case SPI_MEM_DATA_IN: 450 + amd_spi_mem_data_in(amd_spi, op); 451 + break; 452 + case SPI_MEM_DATA_OUT: 453 + fallthrough; 454 + case SPI_MEM_NO_DATA: 455 + amd_spi_mem_data_out(amd_spi, op); 456 + break; 457 + default: 458 + ret = -EOPNOTSUPP; 459 + } 460 + 461 + return ret; 462 + } 463 + 464 + static const struct spi_controller_mem_ops amd_spi_mem_ops = { 465 + .exec_op = amd_spi_exec_mem_op, 466 + .adjust_op_size = amd_spi_adjust_op_size, 467 + .supports_op = amd_spi_supports_op, 468 + }; 469 + 363 470 static int amd_spi_host_transfer(struct spi_controller *host, 364 471 struct spi_message *msg) 365 472 { ··· 520 409 host->min_speed_hz = AMD_SPI_MIN_HZ; 521 410 host->setup = amd_spi_host_setup; 522 411 host->transfer_one_message = amd_spi_host_transfer; 412 + host->mem_ops = &amd_spi_mem_ops; 523 413 host->max_transfer_size = amd_spi_max_transfer_size; 524 414 host->max_message_size = amd_spi_max_transfer_size; 525 415