void mrfld_early_console_init(void) { u32 ctrlr0 = 0; set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, MRFLD_REGBASE_SSP5); pssp = (void *)(__fix_to_virt(FIX_EARLYCON_MEM_BASE) + (MRFLD_REGBASE_SSP5 & (PAGE_SIZE - 1))); if (intel_mid_identify_sim() == INTEL_MID_CPU_SIMULATION_NONE) ssp_timing_wr = 1; /* mask interrupts, clear enable and set DSS config */ /* SSPSCLK on active transfers only */ if (intel_mid_identify_sim() != INTEL_MID_CPU_SIMULATION_SLE) { if (ssp_timing_wr) { dw_writel(pssp, ctrl0, 0xc12c0f); dw_writel(pssp, ctrl1, 0x0); } else { dw_writel(pssp, ctrl0, 0xc0000f); dw_writel(pssp, ctrl1, 0x10000000); } } dw_readl(pssp, sr); /* enable port */ if (intel_mid_identify_sim() != INTEL_MID_CPU_SIMULATION_SLE) { ctrlr0 = dw_readl(pssp, ctrl0); ctrlr0 |= 0x80; dw_writel(pssp, ctrl0, ctrlr0); } }
static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) { struct i2c_msg *msgs = dev->msgs; u32 ic_con; /* Disable the adapter */ dw_writel(dev, 0, DW_IC_ENABLE); /* set the slave (target) address */ dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR); /* if the slave address is ten bit address, enable 10BITADDR */ ic_con = dw_readl(dev, DW_IC_CON); if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) ic_con |= DW_IC_CON_10BITADDR_MASTER; else ic_con &= ~DW_IC_CON_10BITADDR_MASTER; dw_writel(dev, ic_con, DW_IC_CON); /* Enable the adapter */ dw_writel(dev, 1, DW_IC_ENABLE); /* Enable interrupts */ dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK); }
/* Restart the controller, disable all interrupts, clean rx fifo */ static void spi_hw_init(struct device *dev, struct dw_spi *dws) { spi_reset_chip(dws); /* * Try to detect the FIFO depth if not set by interface driver, * the depth could be from 2 to 256 from HW spec */ if (!dws->fifo_len) { u32 fifo; for (fifo = 1; fifo < 256; fifo++) { dw_writel(dws, DW_SPI_TXFLTR, fifo); if (fifo != dw_readl(dws, DW_SPI_TXFLTR)) break; } dw_writel(dws, DW_SPI_TXFLTR, 0); dws->fifo_len = (fifo == 1) ? 0 : fifo; dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len); } /* enable HW fixup for explicit CS deselect for Amazon's alpine chip */ if (dws->cs_override) dw_writel(dws, DW_SPI_CS_OVERRIDE, 0xF); }
void i2c_dw_disable(struct dw_i2c_dev *dev) { /* Disable controller */ dw_writel(dev, 0, DW_IC_ENABLE); /* Disable all interupts */ dw_writel(dev, 0, DW_IC_INTR_MASK); dw_readl(dev, DW_IC_CLR_INTR); }
static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev) { /* Configure Tx/Rx FIFO threshold levels */ dw_writel(dev, dev->tx_fifo_depth / 2, DW_IC_TX_TL); dw_writel(dev, 0, DW_IC_RX_TL); /* Configure the I2C master */ dw_writel(dev, dev->master_cfg, DW_IC_CON); }
static int mfld_i2c_scl_cfg(struct dw_i2c_dev *dev) { dw_writel(dev, PNW_SS_SCLK_HCNT, DW_IC_SS_SCL_HCNT); dw_writel(dev, PNW_SS_SCLK_LCNT, DW_IC_SS_SCL_LCNT); dw_writel(dev, PNW_FS_SCLK_HCNT, DW_IC_FS_SCL_HCNT); dw_writel(dev, PNW_FS_SCLK_LCNT, DW_IC_FS_SCL_LCNT); return 0; }
static int ctp_i2c_scl_cfg(struct dw_i2c_dev *dev) { dw_writel(dev, CLV_SS_SCLK_HCNT, DW_IC_SS_SCL_HCNT); dw_writel(dev, CLV_SS_SCLK_LCNT, DW_IC_SS_SCL_LCNT); dw_writel(dev, CLV_FS_SCLK_HCNT, DW_IC_FS_SCL_HCNT); dw_writel(dev, CLV_FS_SCLK_LCNT, DW_IC_FS_SCL_LCNT); return 0; }
void dw_spi_set_cs(struct spi_device *spi, bool enable) { struct dw_spi *dws = spi_controller_get_devdata(spi->controller); struct chip_data *chip = spi_get_ctldata(spi); if (chip && chip->cs_control) chip->cs_control(enable); if (enable) dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select)); else if (dws->cs_override) dw_writel(dws, DW_SPI_SER, 0); }
/* Translate char to a eligible word and send to max3110 */ static void max3110_spi_write_data(char c) { u16 data; data = 0x8000 | c; dw_writel(pspi, dr, data); }
/* * Interrupt service routine. This gets called whenever an I2C interrupt * occurs. */ irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) { struct dw_i2c_dev *dev = dev_id; u32 stat, enabled; enabled = dw_readl(dev, DW_IC_ENABLE); stat = dw_readl(dev, DW_IC_RAW_INTR_STAT); dev_dbg(dev->dev, "%s: %s enabled= 0x%x stat=0x%x\n", __func__, dev->adapter.name, enabled, stat); if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY)) return IRQ_NONE; stat = i2c_dw_read_clear_intrbits(dev); if (stat & DW_IC_INTR_TX_ABRT) { dev->cmd_err |= DW_IC_ERR_TX_ABRT; dev->status = STATUS_IDLE; /* * Anytime TX_ABRT is set, the contents of the tx/rx * buffers are flushed. Make sure to skip them. */ dw_writel(dev, 0, DW_IC_INTR_MASK); goto tx_aborted; } if (stat & DW_IC_INTR_RX_OVER) { dev_err(dev->dev, "i2c fifo overflow rx tl=%d,rxflr=%d,msg len=%d,txflr=%d\n", readl(dev->base + DW_IC_RX_TL),readl(dev->base+DW_IC_RXFLR),dev->msgs[dev->msg_write_idx].len, readl(dev->base + DW_IC_TXFLR)); dev->msg_err = -EINVAL; goto tx_aborted; } if (stat & DW_IC_INTR_RX_FULL) i2c_dw_read(dev); if (stat & DW_IC_INTR_TX_EMPTY) i2c_dw_xfer_msg(dev); if (stat & DW_IC_INTR_STOP_DET) { if (dev->status & STATUS_READ_IN_PROGRESS) i2c_dw_read(dev); if (dev->status !=0) { dev_err(dev->dev, "i2c transfer was stopped unexpected\n"); dev->msg_err = -EINVAL; } } /* * No need to modify or disable the interrupt mask here. * i2c_dw_xfer_msg() will take care of it according to * the current transmit status. */ tx_aborted: if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) complete(&dev->cmd_complete); return IRQ_HANDLED; }
/* Set the ratio rate to 115200, 8n1, IRQ disabled */ static void max3110_spi_write_config(void) { u16 config; config = 0xc001; dw_writel(pspi, dr, config); }
/** * i2c_dw_init() - Initialize the designware I2C master hardware * @dev: device private data * * This functions configures and enables the I2C master. * This function is called during I2C init function, and in case of timeout at * run time. */ static int i2c_dw_init_master(struct dw_i2c_dev *dev) { int ret; ret = i2c_dw_acquire_lock(dev); if (ret) return ret; /* Disable the adapter */ __i2c_dw_disable(dev); /* Write standard speed timing parameters */ dw_writel(dev, dev->ss_hcnt, DW_IC_SS_SCL_HCNT); dw_writel(dev, dev->ss_lcnt, DW_IC_SS_SCL_LCNT); /* Write fast mode/fast mode plus timing parameters */ dw_writel(dev, dev->fs_hcnt, DW_IC_FS_SCL_HCNT); dw_writel(dev, dev->fs_lcnt, DW_IC_FS_SCL_LCNT); /* Write high speed timing parameters if supported */ if (dev->hs_hcnt && dev->hs_lcnt) { dw_writel(dev, dev->hs_hcnt, DW_IC_HS_SCL_HCNT); dw_writel(dev, dev->hs_lcnt, DW_IC_HS_SCL_LCNT); } /* Write SDA hold time if supported */ if (dev->sda_hold_time) dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD); i2c_dw_configure_fifo_master(dev); i2c_dw_release_lock(dev); return 0; }
static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) { struct i2c_msg *msgs = dev->msgs; u32 ic_con, ic_tar = 0; /* Disable the adapter */ __i2c_dw_disable(dev); /* If the slave address is ten bit address, enable 10BITADDR */ ic_con = dw_readl(dev, DW_IC_CON); if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) { ic_con |= DW_IC_CON_10BITADDR_MASTER; /* * If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing * mode has to be enabled via bit 12 of IC_TAR register. * We set it always as I2C_DYNAMIC_TAR_UPDATE can't be * detected from registers. */ ic_tar = DW_IC_TAR_10BITADDR_MASTER; } else { ic_con &= ~DW_IC_CON_10BITADDR_MASTER; } dw_writel(dev, ic_con, DW_IC_CON); /* * Set the slave (target) address and enable 10-bit addressing mode * if applicable. */ dw_writel(dev, msgs[dev->msg_write_idx].addr | ic_tar, DW_IC_TAR); /* Enforce disabled interrupts (due to HW issues) */ i2c_dw_disable_int(dev); /* Enable the adapter */ __i2c_dw_enable(dev); /* Dummy read to avoid the register getting stuck on Bay Trail */ dw_readl(dev, DW_IC_ENABLE_STATUS); /* Clear and enable interrupts */ dw_readl(dev, DW_IC_CLR_INTR); dw_writel(dev, DW_IC_INTR_MASTER_MASK, DW_IC_INTR_MASK); }
/* similar to max3110_spi_write_data, but via SSP controller */ static void max3110_ssp_write_data(char c) { u16 data; data = 0x8000 | c; dw_writel(pssp, dr, data); dw_readl(pssp, dr); udelay(10); return; }
/* similar to max3110_spi_write_config, but via SSP controller */ static void max3110_ssp_write_config(void) { u16 config; config = 0xc001; dw_writel(pssp, dr, config); dw_readl(pssp, dr); udelay(10); return; }
/* VLV2 PCI config space memio access to the controller is * enabled by * 1. Reset 0x804 and 0x808 offset from base address. * 2. Set 0x804 offset from base address to 0x3. */ static void vlv2_reset(struct dw_i2c_dev *dev) { int i; for (i = 0; i < 10; i++) { dw_writel(dev, 0, 0x804); dw_writel(dev, 0, 0x808); usleep_range(10, 100); dw_writel(dev, 3, 0x804); usleep_range(10, 100); if (dw_readl(dev, DW_IC_COMP_TYPE) != DW_IC_COMP_TYPE_VALUE) continue; return; } dev_warn(dev->dev, "vlv2 I2C reset failed\n"); }
/* * Interrupt service routine. This gets called whenever an I2C master interrupt * occurs. */ static int i2c_dw_irq_handler_master(struct dw_i2c_dev *dev) { u32 stat; stat = i2c_dw_read_clear_intrbits(dev); if (stat & DW_IC_INTR_TX_ABRT) { dev->cmd_err |= DW_IC_ERR_TX_ABRT; dev->status = STATUS_IDLE; /* * Anytime TX_ABRT is set, the contents of the tx/rx * buffers are flushed. Make sure to skip them. */ dw_writel(dev, 0, DW_IC_INTR_MASK); goto tx_aborted; } if (stat & DW_IC_INTR_RX_FULL) i2c_dw_read(dev); if (stat & DW_IC_INTR_TX_EMPTY) i2c_dw_xfer_msg(dev); /* * No need to modify or disable the interrupt mask here. * i2c_dw_xfer_msg() will take care of it according to * the current transmit status. */ tx_aborted: if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) complete(&dev->cmd_complete); else if (unlikely(dev->flags & ACCESS_INTR_MASK)) { /* Workaround to trigger pending interrupt */ stat = dw_readl(dev, DW_IC_INTR_MASK); i2c_dw_disable_int(dev); dw_writel(dev, stat, DW_IC_INTR_MASK); } return 0; }
void mrst_early_console_init(void) { u32 ctrlr0 = 0; u32 spi0_cdiv; u32 freq; /* Freqency info only need be searched once */ /* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */ pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, MRST_CLK_SPI0_REG); spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9; freq = 100000000 / (spi0_cdiv + 1); if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_PENWELL) mrst_spi_paddr = MRST_REGBASE_SPI1; else if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_CLOVERVIEW) mrst_spi_paddr = CLV_REGBASE_SPI1; pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, mrst_spi_paddr); /* Disable SPI controller */ dw_writel(pspi, ssienr, 0); /* Set control param, 8 bits, transmit only mode */ ctrlr0 = dw_readl(pspi, ctrl0); ctrlr0 &= 0xfcc0; ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET) | (SPI_TMOD_TO << SPI_TMOD_OFFSET); dw_writel(pspi, ctrl0, ctrlr0); /* * Change the spi0 clk to comply with 115200 bps, use 100000 to * calculate the clk dividor to make the clock a little slower * than real baud rate. */ dw_writel(pspi, baudr, freq/100000); /* Disable all INT for early phase */ dw_writel(pspi, imr, 0x0); /* Set the cs to spi-uart */ dw_writel(pspi, ser, 0x2); /* Enable the HW, the last step for HW init */ dw_writel(pspi, ssienr, 0x1); /* Set the default configuration */ max3110_spi_write_config(); /* Register the kmsg dumper */ if (!dumper_registered) { dw_dumper.dump = dw_kmsg_dump; kmsg_dump_register(&dw_dumper); dumper_registered = 1; } }
static int vlv2_i2c_scl_cfg(struct dw_i2c_dev *dev) { dw_writel(dev, VLV2_SS_SCLK_HCNT, DW_IC_SS_SCL_HCNT); dw_writel(dev, VLV2_SS_SCLK_LCNT, DW_IC_SS_SCL_LCNT); if (dev->fast_plus) { dw_writel(dev, VLV2_FS_P_SCLK_HCNT, DW_IC_FS_SCL_HCNT); dw_writel(dev, VLV2_FS_P_SCLK_LCNT, DW_IC_FS_SCL_LCNT); } else { dw_writel(dev, VLV2_FS_SCLK_HCNT, DW_IC_FS_SCL_HCNT); dw_writel(dev, VLV2_FS_SCLK_LCNT, DW_IC_FS_SCL_LCNT); } dw_writel(dev, VLV2_HS_SCLK_HCNT, DW_IC_HS_SCL_HCNT); dw_writel(dev, VLV2_HS_SCLK_LCNT, DW_IC_HS_SCL_LCNT); return 0; }
/* * Interrupt service routine. This gets called whenever an I2C interrupt * occurs. */ irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) { struct dw_i2c_dev *dev = dev_id; u32 stat, enabled; enabled = dw_readl(dev, DW_IC_ENABLE); stat = dw_readl(dev, DW_IC_RAW_INTR_STAT); dev_dbg(dev->dev, "%s: %s enabled= 0x%x stat=0x%x\n", __func__, dev->adapter.name, enabled, stat); if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY)) return IRQ_NONE; stat = i2c_dw_read_clear_intrbits(dev); if (stat & DW_IC_INTR_TX_ABRT) { dev->cmd_err |= DW_IC_ERR_TX_ABRT; dev->status = STATUS_IDLE; /* * Anytime TX_ABRT is set, the contents of the tx/rx * buffers are flushed. Make sure to skip them. */ dw_writel(dev, 0, DW_IC_INTR_MASK); goto tx_aborted; } if (stat & DW_IC_INTR_RX_FULL) i2c_dw_read(dev); if (stat & DW_IC_INTR_TX_EMPTY) i2c_dw_xfer_msg(dev); /* * No need to modify or disable the interrupt mask here. * i2c_dw_xfer_msg() will take care of it according to * the current transmit status. */ tx_aborted: if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) complete(&dev->cmd_complete); return IRQ_HANDLED; }
static int merr_i2c_scl_cfg(struct dw_i2c_dev *dev) { dw_writel(dev, MERR_SS_SCLK_HCNT, DW_IC_SS_SCL_HCNT); dw_writel(dev, MERR_SS_SCLK_LCNT, DW_IC_SS_SCL_LCNT); dw_writel(dev, MERR_FS_SCLK_HCNT, DW_IC_FS_SCL_HCNT); dw_writel(dev, MERR_FS_SCLK_LCNT, DW_IC_FS_SCL_LCNT); dw_writel(dev, MERR_HS_SCLK_HCNT, DW_IC_HS_SCL_HCNT); dw_writel(dev, MERR_HS_SCLK_LCNT, DW_IC_HS_SCL_LCNT); return 0; }
static int chv_i2c_scl_cfg(struct dw_i2c_dev *dev) { dw_writel(dev, CHV_SS_SCLK_HCNT, DW_IC_SS_SCL_HCNT); dw_writel(dev, CHV_SS_SCLK_LCNT, DW_IC_SS_SCL_LCNT); if (dev->fast_plus) { dw_writel(dev, CHV_FS_P_SCLK_HCNT, DW_IC_FS_SCL_HCNT); dw_writel(dev, CHV_FS_P_SCLK_LCNT, DW_IC_FS_SCL_LCNT); } else { dw_writel(dev, CHV_FS_SCLK_HCNT, DW_IC_FS_SCL_HCNT); dw_writel(dev, CHV_FS_SCLK_LCNT, DW_IC_FS_SCL_LCNT); } return 0; }
static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) { struct i2c_msg *msgs = dev->msgs; u32 ic_con; int i; /* Disable the adapter */ dw_writel(dev, 0, DW_IC_ENABLE); /* set the slave (target) address */ dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR); /* if the slave address is ten bit address, enable 10BITADDR */ ic_con = dw_readl(dev, DW_IC_CON); if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) ic_con |= DW_IC_CON_10BITADDR_MASTER; else ic_con &= ~DW_IC_CON_10BITADDR_MASTER; dw_writel(dev, ic_con, DW_IC_CON); /* Set receive FIFO threshold level */ for (i = 0; i < dev->msgs_num; i++) { if (msgs[i].flags & I2C_M_RD) { if (msgs[i].len > dev->rx_fifo_depth) dw_writel(dev, get_max_divisor(msgs[i].len, dev->rx_fifo_depth - 2) - 1, DW_IC_RX_TL); else dw_writel(dev, msgs[i].len - 1, DW_IC_RX_TL); } } /* Enable the adapter */ dw_writel(dev, 1, DW_IC_ENABLE); /* Enable interrupts */ dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK); }
/** * i2c_dw_init() - initialize the designware i2c master hardware * @dev: device private data * * This functions configures and enables the I2C master. * This function is called during I2C init function, and in case of timeout at * run time. */ int i2c_dw_init(struct dw_i2c_dev *dev) { u32 input_clock_khz; u32 hcnt, lcnt; u32 reg; u32 cycle; input_clock_khz = dev->get_clk_rate_khz(dev); /* Configure register endianess access */ reg = dw_readl(dev, DW_IC_COMP_TYPE); if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) { dev->swab = 1; reg = DW_IC_COMP_TYPE_VALUE; } if (reg != DW_IC_COMP_TYPE_VALUE) { dev_err(dev->dev, "Unknown Synopsys component type: " "0x%08x\n", reg); return -ENODEV; } /* Disable the adapter */ dw_writel(dev, 0, DW_IC_ENABLE); /* set standard and fast speed deviders for high/low periods */ /* Standard-mode */ hcnt = i2c_dw_scl_hcnt(input_clock_khz, 40, /* tHD;STA = tHIGH = 4.0 us */ 8, /* tf = 0.3 us */ 0, /* 0: DW default, 1: Ideal */ 0); /* No offset */ lcnt = i2c_dw_scl_lcnt(input_clock_khz, 47, /* tLOW = 4.7 us */ 6, /* tf = 0.3 us */ 0); /* No offset */ dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT); dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT); dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); /* Fast-mode */ hcnt = i2c_dw_scl_hcnt(input_clock_khz, 6, /* tHD;STA = tHIGH = 0.6 us */ 3, /* tf = 0.3 us */ 0, /* 0: DW default, 1: Ideal */ 0); /* No offset */ lcnt = i2c_dw_scl_lcnt(input_clock_khz, 13, /* tLOW = 1.3 us */ 3, /* tf = 0.3 us */ 0); /* No offset */ dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT); dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT); dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); /* Configure Tx/Rx FIFO threshold levels */ dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL); dw_writel(dev, 0, DW_IC_RX_TL); /* Calculate cycle time, the unit is ns */ cycle = 1000000 / input_clock_khz; /* Set sda hold time as 200 ns */ dw_writel(dev, 200/cycle, DW_IC_SDA_HOLD); /* configure the i2c master */ dw_writel(dev, dev->master_cfg , DW_IC_CON); return 0; }
/* * Initiate (and continue) low level master read/write transaction. * This function is only called from i2c_dw_isr, and pumping i2c_msg * messages into the tx buffer. Even if the size of i2c_msg data is * longer than the size of the tx buffer, it handles everything. */ void i2c_dw_xfer_msg(struct dw_i2c_dev *dev) { struct i2c_msg *msgs = dev->msgs; u32 intr_mask; int tx_limit, rx_limit; u32 addr = msgs[dev->msg_write_idx].addr; u32 buf_len = dev->tx_buf_len; u8 *buf = dev->tx_buf; intr_mask = DW_IC_INTR_DEFAULT_MASK; for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) { /* * if target address has changed, we need to * reprogram the target address in the i2c * adapter when we are done with this transfer */ if (msgs[dev->msg_write_idx].addr != addr) { dev_err(dev->dev, "%s: invalid target address\n", __func__); dev->msg_err = -EINVAL; break; } if (msgs[dev->msg_write_idx].len == 0) { dev_err(dev->dev, "%s: invalid message length\n", __func__); dev->msg_err = -EINVAL; break; } if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { /* new i2c_msg */ buf = msgs[dev->msg_write_idx].buf; buf_len = msgs[dev->msg_write_idx].len; } tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR); rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR); while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { dw_writel(dev, 0x100, DW_IC_DATA_CMD); rx_limit--; } else dw_writel(dev, *buf++, DW_IC_DATA_CMD); tx_limit--; buf_len--; } dev->tx_buf = buf; dev->tx_buf_len = buf_len; if (buf_len > 0) { /* more bytes to be written */ dev->status |= STATUS_WRITE_IN_PROGRESS; break; } else dev->status &= ~STATUS_WRITE_IN_PROGRESS; } /* * If i2c_msg index search is completed, we don't need TX_EMPTY * interrupt any more. */ if (dev->msg_write_idx == dev->msgs_num) intr_mask &= ~DW_IC_INTR_TX_EMPTY; if (dev->msg_err) intr_mask = 0; dw_writel(dev, intr_mask, DW_IC_INTR_MASK); }
/* * Prepare controller for a transaction and call i2c_dw_xfer_msg */ int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { struct dw_i2c_dev *dev = i2c_get_adapdata(adap); int ret; dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); mutex_lock(&dev->lock); pm_runtime_get_sync(dev->dev); INIT_COMPLETION(dev->cmd_complete); dev->msgs = msgs; dev->msgs_num = num; dev->cmd_err = 0; dev->msg_write_idx = 0; dev->msg_read_idx = 0; dev->msg_err = 0; dev->status = STATUS_IDLE; dev->abort_source = 0; ret = i2c_dw_wait_bus_not_busy(dev); if (ret < 0) goto done; /* start the transfers */ i2c_dw_xfer_init(dev); /* wait for tx to complete */ // ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ); ret = wait_for_completion_timeout(&dev->cmd_complete, HZ); if (ret == 0) { dev_err(dev->dev, "controller timed out\n"); i2c_dw_init(dev); ret = -ETIMEDOUT; goto done; } else if (ret < 0) goto done; if (dev->msg_err) { ret = dev->msg_err; goto done; } /* no error */ if (likely(!dev->cmd_err)) { /* Disable the adapter */ dw_writel(dev, 0, DW_IC_ENABLE); ret = num; goto done; } /* We have an error */ if (dev->cmd_err == DW_IC_ERR_TX_ABRT) { ret = i2c_dw_handle_tx_abort(dev); goto done; } ret = -EIO; done: pm_runtime_put(dev->dev); mutex_unlock(&dev->lock); return ret; }
void i2c_dw_enable(struct dw_i2c_dev *dev) { /* Enable the adapter */ dw_writel(dev, 1, DW_IC_ENABLE); }
void i2c_dw_disable_int(struct dw_i2c_dev *dev) { dw_writel(dev, 0, DW_IC_INTR_MASK); }
static int dw_spi_transfer_one(struct spi_controller *master, struct spi_device *spi, struct spi_transfer *transfer) { struct dw_spi *dws = spi_controller_get_devdata(master); struct chip_data *chip = spi_get_ctldata(spi); u8 imask = 0; u16 txlevel = 0; u32 cr0; int ret; dws->dma_mapped = 0; dws->tx = (void *)transfer->tx_buf; dws->tx_end = dws->tx + transfer->len; dws->rx = transfer->rx_buf; dws->rx_end = dws->rx + transfer->len; dws->len = transfer->len; spi_enable_chip(dws, 0); /* Handle per transfer options for bpw and speed */ if (transfer->speed_hz != dws->current_freq) { if (transfer->speed_hz != chip->speed_hz) { /* clk_div doesn't support odd number */ chip->clk_div = (DIV_ROUND_UP(dws->max_freq, transfer->speed_hz) + 1) & 0xfffe; chip->speed_hz = transfer->speed_hz; } dws->current_freq = transfer->speed_hz; spi_set_clk(dws, chip->clk_div); } dws->n_bytes = DIV_ROUND_UP(transfer->bits_per_word, BITS_PER_BYTE); dws->dma_width = DIV_ROUND_UP(transfer->bits_per_word, BITS_PER_BYTE); /* Default SPI mode is SCPOL = 0, SCPH = 0 */ cr0 = (transfer->bits_per_word - 1) | (chip->type << SPI_FRF_OFFSET) | ((((spi->mode & SPI_CPOL) ? 1 : 0) << SPI_SCOL_OFFSET) | (((spi->mode & SPI_CPHA) ? 1 : 0) << SPI_SCPH_OFFSET)) | (chip->tmode << SPI_TMOD_OFFSET); /* * Adjust transfer mode if necessary. Requires platform dependent * chipselect mechanism. */ if (chip->cs_control) { if (dws->rx && dws->tx) chip->tmode = SPI_TMOD_TR; else if (dws->rx) chip->tmode = SPI_TMOD_RO; else chip->tmode = SPI_TMOD_TO; cr0 &= ~SPI_TMOD_MASK; cr0 |= (chip->tmode << SPI_TMOD_OFFSET); } dw_writel(dws, DW_SPI_CTRL0, cr0); /* Check if current transfer is a DMA transaction */ if (master->can_dma && master->can_dma(master, spi, transfer)) dws->dma_mapped = master->cur_msg_mapped; /* For poll mode just disable all interrupts */ spi_mask_intr(dws, 0xff); /* * Interrupt mode * we only need set the TXEI IRQ, as TX/RX always happen syncronizely */ if (dws->dma_mapped) { ret = dws->dma_ops->dma_setup(dws, transfer); if (ret < 0) { spi_enable_chip(dws, 1); return ret; } } else if (!chip->poll_mode) { txlevel = min_t(u16, dws->fifo_len / 2, dws->len / dws->n_bytes); dw_writel(dws, DW_SPI_TXFLTR, txlevel); /* Set the interrupt mask */ imask |= SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI; spi_umask_intr(dws, imask); dws->transfer_handler = interrupt_transfer; } spi_enable_chip(dws, 1); if (dws->dma_mapped) { ret = dws->dma_ops->dma_transfer(dws, transfer); if (ret < 0) return ret; } if (chip->poll_mode) return poll_transfer(dws); return 1; }
/* * Initiate (and continue) low level master read/write transaction. * This function is only called from i2c_dw_isr, and pumping i2c_msg * messages into the tx buffer. Even if the size of i2c_msg data is * longer than the size of the tx buffer, it handles everything. */ static void i2c_dw_xfer_msg(struct dw_i2c_dev *dev) { struct i2c_msg *msgs = dev->msgs; u32 intr_mask; int tx_limit, rx_limit; u32 addr = msgs[dev->msg_write_idx].addr; u32 buf_len = dev->tx_buf_len; u8 *buf = dev->tx_buf; bool need_restart = false; intr_mask = DW_IC_INTR_MASTER_MASK; for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) { u32 flags = msgs[dev->msg_write_idx].flags; /* * If target address has changed, we need to * reprogram the target address in the I2C * adapter when we are done with this transfer. */ if (msgs[dev->msg_write_idx].addr != addr) { dev_err(dev->dev, "%s: invalid target address\n", __func__); dev->msg_err = -EINVAL; break; } if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { /* new i2c_msg */ buf = msgs[dev->msg_write_idx].buf; buf_len = msgs[dev->msg_write_idx].len; /* If both IC_EMPTYFIFO_HOLD_MASTER_EN and * IC_RESTART_EN are set, we must manually * set restart bit between messages. */ if ((dev->master_cfg & DW_IC_CON_RESTART_EN) && (dev->msg_write_idx > 0)) need_restart = true; } tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR); rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR); while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { u32 cmd = 0; /* * If IC_EMPTYFIFO_HOLD_MASTER_EN is set we must * manually set the stop bit. However, it cannot be * detected from the registers so we set it always * when writing/reading the last byte. */ /* * i2c-core always sets the buffer length of * I2C_FUNC_SMBUS_BLOCK_DATA to 1. The length will * be adjusted when receiving the first byte. * Thus we can't stop the transaction here. */ if (dev->msg_write_idx == dev->msgs_num - 1 && buf_len == 1 && !(flags & I2C_M_RECV_LEN)) cmd |= BIT(9); if (need_restart) { cmd |= BIT(10); need_restart = false; } if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { /* Avoid rx buffer overrun */ if (dev->rx_outstanding >= dev->rx_fifo_depth) break; dw_writel(dev, cmd | 0x100, DW_IC_DATA_CMD); rx_limit--; dev->rx_outstanding++; } else dw_writel(dev, cmd | *buf++, DW_IC_DATA_CMD); tx_limit--; buf_len--; } dev->tx_buf = buf; dev->tx_buf_len = buf_len; /* * Because we don't know the buffer length in the * I2C_FUNC_SMBUS_BLOCK_DATA case, we can't stop * the transaction here. */ if (buf_len > 0 || flags & I2C_M_RECV_LEN) { /* more bytes to be written */ dev->status |= STATUS_WRITE_IN_PROGRESS; break; } else dev->status &= ~STATUS_WRITE_IN_PROGRESS; } /* * If i2c_msg index search is completed, we don't need TX_EMPTY * interrupt any more. */ if (dev->msg_write_idx == dev->msgs_num) intr_mask &= ~DW_IC_INTR_TX_EMPTY; if (dev->msg_err) intr_mask = 0; dw_writel(dev, intr_mask, DW_IC_INTR_MASK); }