1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * LPC32xx SSP interface (SPI mode) 4 * 5 * (C) Copyright 2014 DENX Software Engineering GmbH 6 * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr> 7 */ 8 9 #include <common.h> 10 #include <linux/compat.h> 11 #include <asm/io.h> 12 #include <malloc.h> 13 #include <spi.h> 14 #include <asm/arch/clk.h> 15 16 /* SSP chip registers */ 17 struct ssp_regs { 18 u32 cr0; 19 u32 cr1; 20 u32 data; 21 u32 sr; 22 u32 cpsr; 23 u32 imsc; 24 u32 ris; 25 u32 mis; 26 u32 icr; 27 u32 dmacr; 28 }; 29 30 /* CR1 register defines */ 31 #define SSP_CR1_SSP_ENABLE 0x0002 32 33 /* SR register defines */ 34 #define SSP_SR_TNF 0x0002 35 /* SSP status RX FIFO not empty bit */ 36 #define SSP_SR_RNE 0x0004 37 38 /* lpc32xx spi slave */ 39 struct lpc32xx_spi_slave { 40 struct spi_slave slave; 41 struct ssp_regs *regs; 42 }; 43 44 static inline struct lpc32xx_spi_slave *to_lpc32xx_spi_slave( 45 struct spi_slave *slave) 46 { 47 return container_of(slave, struct lpc32xx_spi_slave, slave); 48 } 49 50 /* spi_init is called during boot when CONFIG_CMD_SPI is defined */ 51 void spi_init(void) 52 { 53 /* 54 * nothing to do: clocking was enabled in lpc32xx_ssp_enable() 55 * and configuration will be done in spi_setup_slave() 56 */ 57 } 58 59 /* the following is called in sequence by do_spi_xfer() */ 60 61 struct spi_slave *spi_setup_slave(uint bus, uint cs, uint max_hz, uint mode) 62 { 63 struct lpc32xx_spi_slave *lslave; 64 65 /* we only set up SSP0 for now, so ignore bus */ 66 67 if (mode & SPI_3WIRE) { 68 pr_err("3-wire mode not supported"); 69 return NULL; 70 } 71 72 if (mode & SPI_SLAVE) { 73 pr_err("slave mode not supported\n"); 74 return NULL; 75 } 76 77 if (mode & SPI_PREAMBLE) { 78 pr_err("preamble byte skipping not supported\n"); 79 return NULL; 80 } 81 82 lslave = spi_alloc_slave(struct lpc32xx_spi_slave, bus, cs); 83 if (!lslave) { 84 printf("SPI_error: Fail to allocate lpc32xx_spi_slave\n"); 85 return NULL; 86 } 87 88 lslave->regs = (struct ssp_regs *)SSP0_BASE; 89 90 /* 91 * 8 bit frame, SPI fmt, 500kbps -> clock divider is 26. 92 * Set SCR to 0 and CPSDVSR to 26. 93 */ 94 95 writel(0x7, &lslave->regs->cr0); /* 8-bit chunks, SPI, 1 clk/bit */ 96 writel(26, &lslave->regs->cpsr); /* SSP clock = HCLK/26 = 500kbps */ 97 writel(0, &lslave->regs->imsc); /* do not raise any interrupts */ 98 writel(0, &lslave->regs->icr); /* clear any pending interrupt */ 99 writel(0, &lslave->regs->dmacr); /* do not do DMAs */ 100 writel(SSP_CR1_SSP_ENABLE, &lslave->regs->cr1); /* enable SSP0 */ 101 return &lslave->slave; 102 } 103 104 void spi_free_slave(struct spi_slave *slave) 105 { 106 struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave); 107 108 debug("(lpc32xx) spi_free_slave: 0x%08x\n", (u32)lslave); 109 free(lslave); 110 } 111 112 int spi_claim_bus(struct spi_slave *slave) 113 { 114 /* only one bus and slave so far, always available */ 115 return 0; 116 } 117 118 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, 119 const void *dout, void *din, unsigned long flags) 120 { 121 struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave); 122 int bytelen = bitlen >> 3; 123 int idx_out = 0; 124 int idx_in = 0; 125 int start_time; 126 127 start_time = get_timer(0); 128 while ((idx_out < bytelen) || (idx_in < bytelen)) { 129 int status = readl(&lslave->regs->sr); 130 if ((idx_out < bytelen) && (status & SSP_SR_TNF)) 131 writel(((u8 *)dout)[idx_out++], &lslave->regs->data); 132 if ((idx_in < bytelen) && (status & status & SSP_SR_RNE)) 133 ((u8 *)din)[idx_in++] = readl(&lslave->regs->data); 134 if (get_timer(start_time) >= CONFIG_LPC32XX_SSP_TIMEOUT) 135 return -1; 136 } 137 return 0; 138 } 139 140 void spi_release_bus(struct spi_slave *slave) 141 { 142 /* do nothing */ 143 } 144