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