void spi_init(void) { putreg16(SPI_SET1_EN_CLK | SPI_SET1_WR_IRQ_DIS | SPI_SET1_RDWR_IRQ_DIS, SPI_REG(REG_SET1)); putreg16(0x0001, SPI_REG(REG_SET2)); }
static void reset_spimaster(void) { SPI_REG(SPIGCR0) = 0x00000000; mdelay(1); // Delay for a bit SPI_REG(SPIGCR0) = 0x00000001; SPI_REG(SPIGCR1) = 0x00000003; //SPIGCR1 CLKMODºÍMASTERMOD }
static u32 pch_read_soft_strap(int id) { clrbits_le32(SPI_REG(SPIBAR_FDOC), 0x00007ffc); setbits_le32(SPI_REG(SPIBAR_FDOC), 0x00004000 | id * 4); return readl(SPI_REG(SPIBAR_FDOD)); }
// Reading from the SPI device ssize_t dv_spi_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { Uarray buf_val; ssize_t status = 0; if((NULL == buf)||(count <= 0)) { return -1; } #if 0 len = kfifo_len(g_kfifo); if(count > len) { count = len ; } memset(g_readbuf,0,sizeof(g_readbuf)); kfifo_get(g_kfifo,g_readbuf,count); // Transferring data to user space status = copy_to_user(buf, g_readbuf, count); if(0 == status) { return count; } else { return -1; } #else if(SPIBUF_RXEMPTY_MASK & SPI_REG(SPIBUF)) { buf_val.udata = SPI_REG(SPIBUF); count = (g_dataformat == format_8bit)?1:2; // Transferring data to user space status = copy_to_user(buf, buf_val.uarray,count); if(0 == status) { return count; } else { return -1; } } else { return -1; } #endif }
// Called when a userspace program closes the file int dv_spi_release(struct inode *inode, struct file *filp) { printk("\nclose\n"); // Place SPI peripheral into reset SPI_REG(SPIGCR0) = 0; // Remove the SPI output on the GPIO SPI_REG(PINMUX1REG) &= (~0x00000100); // Disable the clock thus removing power from the peripheral if (g_clkptr) { clk_disable(g_clkptr); } g_clkptr = NULL; return 0; }
BOOL CPU_SPI_Xaction_nWrite8_nRead8( SPI_XACTION_8& Transaction ) { LPC_SSP_T *spi = SPI_REG(Transaction.SPI_mod); UINT8* outBuf = Transaction.Write8; UINT8* inBuf = Transaction.Read8; INT32 outLen = Transaction.WriteCount; INT32 num, ii, i = 0; if (Transaction.ReadCount) { // write & read num = Transaction.ReadCount + Transaction.ReadStartOffset; ii = -Transaction.ReadStartOffset; } else { // write only num = outLen; ii = 0x80000000; // disable write to inBuf } UINT8 out = outBuf[0]; UINT16 in; SPI_Write(spi, out); // write first word while (++i < num) { if (i < outLen) out = outBuf[i]; // get new output data while (!(SPI_Readable(spi))); // wait for Rx buffer in = SPI_Read(spi); // read input SPI_Write(spi, out); // start output if (ii >= 0) inBuf[ii] = (UINT8)in; // save input data ii++; } while (!(SPI_Readable(spi))); // wait for Rx buffer in = SPI_Read(spi); // read last input if (ii >= 0) inBuf[ii] = (UINT8)in; // save last input return TRUE; }
BOOL CPU_SPI_Xaction_Start(const SPI_CONFIGURATION& Configuration) { if (Configuration.SPI_mod >= TOTAL_SPI_PORT) return FALSE; LPC_SSP_T *spi = SPI_REG(Configuration.SPI_mod); int Bits, Mode; // Configure options and clock Bits = (Configuration.MD_16bits) ? 16 : 8; Mode = (Configuration.MSK_IDLE) ? 2 : 0; // ToDo: Check Mode |= (!Configuration.MSK_SampleEdge) ? 1 : 0; SPI_Config(spi, Bits, Mode, 0); SPI_Frequency(spi, (1000 * Configuration.Clock_RateKHz)); // I/O setup GPIO_PIN msk, miso, mosi; CPU_SPI_GetPins(Configuration.SPI_mod, msk, miso, mosi); UINT32 alternate = 0x252; // AF5 = SPI1/SPI2 if (Configuration.SPI_mod == 2) alternate = 0x262; // AF6 = SPI3, speed = 2 (50MHz) CPU_GPIO_DisablePin(msk, RESISTOR_DISABLED, 1, (GPIO_ALT_MODE)alternate); CPU_GPIO_DisablePin(miso, RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)alternate); CPU_GPIO_DisablePin(mosi, RESISTOR_DISABLED, 1, (GPIO_ALT_MODE)alternate); // CS setup CPU_GPIO_EnableOutputPin(Configuration.DeviceCS, Configuration.CS_Active); if(Configuration.CS_Setup_uSecs) { HAL_Time_Sleep_MicroSeconds_InterruptEnabled(Configuration.CS_Setup_uSecs); } return TRUE; }
static void inline wait_untilsend(void) { if(NULL == g_clkptr) { return; } while(SPIBUF_RXEMPTY_MASK & SPI_REG(SPIBUF)) { cpu_relax(); } }
/** * Select SPI Master/Slave BASE, than return correct address */ static u32 spi_get_reg_addr(u8 spi_inst, u32 offset) { switch (spi_inst) { case SPI_MASTER1: return SPI_REG(offset); #if (SPI_INSTANCES > 1) case SPI_MASTER2: return SPI2_REG(offset); #endif # if (SPI_INSTANCES > 2) case SPI_MASTER3: return SPI3_REG(offset); #endif } return 0xffffffff; }
BOOL CPU_SPI_Xaction_Stop(const SPI_CONFIGURATION& Configuration) { LPC_SSP_T *spi = SPI_REG(Configuration.SPI_mod); while (SPI_Busy(spi)); // wait for completion if(Configuration.CS_Hold_uSecs) { HAL_Time_Sleep_MicroSeconds_InterruptEnabled(Configuration.CS_Hold_uSecs); } CPU_GPIO_SetPinState(Configuration.DeviceCS, !Configuration.CS_Active); GPIO_RESISTOR res = RESISTOR_PULLDOWN; if (Configuration.MSK_IDLE) res = RESISTOR_PULLUP; GPIO_PIN msk, miso, mosi; CPU_SPI_GetPins(Configuration.SPI_mod, msk, miso, mosi); CPU_GPIO_EnableInputPin(msk, FALSE, NULL, GPIO_INT_NONE, res); CPU_GPIO_EnableInputPin(miso, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLDOWN); CPU_GPIO_EnableInputPin(mosi, FALSE, NULL, GPIO_INT_NONE, RESISTOR_PULLDOWN); SPI_Disable(spi); // Disable SPI return TRUE; }
int spi_xfer(uint8_t dev_idx, uint8_t bitlen, const void *dout, void *din) { uint8_t bytes_per_xfer; uint8_t reg_status, reg_ctrl = 0; uint32_t tmp; if (bitlen == 0) { return 0; } if (bitlen > 32) { return -1; } if (dev_idx > 4) { return -1; } bytes_per_xfer = bitlen / 8; if (bitlen % 8) { bytes_per_xfer ++; } reg_ctrl |= (bitlen - 1) << SPI_CTRL_NB_SHIFT; reg_ctrl |= (dev_idx & 0x7) << SPI_CTRL_AD_SHIFT; if (bitlen <= 8) { tmp = *(uint8_t *)dout; tmp <<= 24 + (8-bitlen); /* align to MSB */ } else if (bitlen <= 16) { tmp = *(uint16_t *)dout; tmp <<= 16 + (16-bitlen); /* align to MSB */ } else { tmp = *(uint32_t *)dout; tmp <<= (32-bitlen); /* align to MSB */ } dbg("spi_xfer(dev_idx=%u, bitlen=%u, data_out=0x%08x): ", dev_idx, bitlen, tmp); /* fill transmit registers */ putreg16(tmp >> 16, SPI_REG(REG_TX_MSB)); putreg16(tmp & 0xffff, SPI_REG(REG_TX_LSB)); /* initiate transfer */ if (din) { reg_ctrl |= SPI_CTRL_RDWR; } else { reg_ctrl |= SPI_CTRL_WR; } putreg16(reg_ctrl, SPI_REG(REG_CTRL)); dbg("reg_ctrl=0x%04x ", reg_ctrl); /* wait until the transfer is complete */ while (1) { reg_status = getreg16(SPI_REG(REG_STATUS)); dbg("status=0x%04x ", reg_status); if (din && (reg_status & SPI_STATUS_RE)) { break; } else if (reg_status & SPI_STATUS_WE) { break; } } /* FIXME: calibrate how much delay we really need (seven 13MHz cycles) */ usleep(1000); if (din) { tmp = getreg16(SPI_REG(REG_RX_MSB)) << 16; tmp |= getreg16(SPI_REG(REG_RX_LSB)); dbg("data_in=0x%08x ", tmp); if (bitlen <= 8) { *(uint8_t *)din = tmp & 0xff; } else if (bitlen <= 16) { *(uint16_t *)din = tmp & 0xffff; } else { *(uint32_t *)din = tmp; } } dbg("\n"); return 0; }
// This function will initialize the pinmux register // -------------------------------- // Configure GPIO Pins for SPI // -------------------------------- static void init_pinmux(void) { // Enable the SPI pins on the GPIO SPI_REG(PINMUX0REG) = VALUE_PINMUX0REG; SPI_REG(PINMUX1REG) = VALUE_PINMUX1REG; }
ssize_t dv_spi_ioctl(struct inode *inode, struct file *filp,\ enum spi_commands cmd, const unsigned long arg) { int tmp = -1; if((cmd < Cmd_reset) || (cmd > Cmd_Selchip) || (arg < Sel_chip0)||(arg > Sel_chip1)) { return -EINVAL ; } switch(cmd) { case Cmd_reset: { reset_spimaster(); memset(g_readbuf,0,sizeof(g_readbuf)); kfifo_reset(g_kfifo); tmp = 0; } break; case Cmd_enspi: { if(Sel_chip0 == (enum spi_selchip)arg) { SPI_REG(SPIPC0) = 0x00000E01; } else if(Sel_chip1 == (enum spi_selchip)arg) { SPI_REG(SPIPC0) = 0x00000E02; } tmp = 0; } break; case Cmd_dataformat: { g_dataformat = (enum spi_dataformat)arg; tmp = (format_8bit == g_dataformat)?SPIFMT_8BIT:SPIFMT_16BIT; SPI_REG(SPIFMT0) = tmp; SPI_REG(SPIFMT1) = tmp; tmp = 0; } break; case Cmd_Cshold: { g_cshold_mask = (Cs_active_hold == (enum spi_cshold)arg)?BIT(28):0; #if 0 ret = gpio_request(37,NULL); printk("\n gpio_is_valid,ret=%d \n",ret); ret = gpio_direction_output(37,1); printk("\n gpio_direction_output,ret=%d \n",ret); //gpio_direction_output(37, (const unsigned int)arg); #endif } break; case Cmd_Selchip: { g_selchip = (enum spi_selchip)arg; if(Sel_chip0 == g_selchip) { SPI_REG(SPIDAT1) = 0x00000000; SPI_REG(SPIDAT1) = (0x00020000 | g_cshold_mask); SPI_REG(SPIDEF) = 0x00000001; g_chip_mask = (CHIP0_MASK | g_cshold_mask); } else if(Sel_chip1 == g_selchip) { SPI_REG(SPIDAT1) = 0x01000000; SPI_REG(SPIDAT1) = (0x00010000 | g_cshold_mask); SPI_REG(SPIDEF) = 0x00000002; g_chip_mask = (CHIP1_MASK | g_cshold_mask); } SPI_REG(SPIGCR1) = 0x01000003; tmp = 0; } break; default: { tmp = -EINVAL; } break; } return tmp; }
// Writing to the SPI device ssize_t dv_spi_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { size_t index = 0; unsigned int datareg = 0; Uarray buf_val; size_t ret = -1; if((NULL == buf) || (count <= 0) || (count > MAX_BUF_SIZE)) { return -EINVAL ; } buf_val.udata = 0; while((SPI_REG(SPIBUF) & SPIBUF_RXEMPTY_MASK) == 0) { cpu_relax(); } if(format_8bit == g_dataformat) { for(index=0; index<count;) { buf_val.udata = SPI_REG(SPIBUF); if((buf_val.udata & SPIBUF_TXFULL_MASK) == 0) { ret = copy_from_user(&datareg, buf + index, 1); if(ret == 0) { datareg &= (0x000000FF); datareg |= g_chip_mask; SPI_REG(SPIDAT1) = datareg; printk("\n1: datareg=%x\n",datareg); wait_untilsend(); } } index++; } } else if(format_16bit == g_dataformat) { for(index=0; index<count;) { buf_val.udata = SPI_REG(SPIBUF); if((buf_val.udata & SPIBUF_TXFULL_MASK) == 0) { ret = copy_from_user(&datareg, buf + index, 2); if(ret == 0) { datareg &= (0x0000FFFF); datareg |= g_chip_mask; SPI_REG(SPIDAT1) = datareg; wait_untilsend(); SPI_REG(SPIDAT1) = (datareg|0x8000); wait_untilsend(); #if 0 buf_val.udata = SPI_REG(SPIBUF); add2kfifo(&(buf_val.uarray[0]),2); #endif } } index += 2; } } return count; }