int at91_clk_probe(struct udevice *dev) { struct udevice *dev_periph_container, *dev_pmc; struct pmc_platdata *plat = dev_get_platdata(dev); dev_periph_container = dev_get_parent(dev); dev_pmc = dev_get_parent(dev_periph_container); plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev_pmc); return 0; }
static int palmas_ldo_probe(struct udevice *dev) { struct dm_regulator_uclass_platdata *uc_pdata; struct udevice *parent; uc_pdata = dev_get_uclass_platdata(dev); parent = dev_get_parent(dev); int type = dev_get_driver_data(parent); uc_pdata->type = REGULATOR_TYPE_LDO; if (dev->driver_data) { u8 idx = dev->driver_data - 1; uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][idx]; uc_pdata->volt_reg = palmas_ldo_volt[type][idx]; } else { /* check for ldoln and ldousb cases */ if (!strcmp("ldoln", dev->name)) { uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][9]; uc_pdata->volt_reg = palmas_ldo_volt[type][9]; } else if (!strcmp("ldousb", dev->name)) { uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][10]; uc_pdata->volt_reg = palmas_ldo_volt[type][10]; } } return 0; }
static int palmas_ldo_bypass_enable(struct udevice *dev, bool enabled) { int type = dev_get_driver_data(dev_get_parent(dev)); struct dm_regulator_uclass_platdata *p; unsigned int adr; int reg; if (type == TPS65917) { /* bypass available only on LDO1 and LDO2 */ if (dev->driver_data > 2) return -ENOTSUPP; } else if (type == TPS659038) { /* bypass available only on LDO9 */ if (dev->driver_data != 9) return -ENOTSUPP; } p = dev_get_uclass_platdata(dev); adr = p->ctrl_reg; reg = pmic_reg_read(dev->parent, adr); if (reg < 0) return reg; if (enabled) reg |= PALMAS_LDO_BYPASS_EN; else reg &= ~PALMAS_LDO_BYPASS_EN; return pmic_reg_write(dev->parent, adr, reg); }
static int periph_clk_enable(struct clk *clk) { struct pmc_platdata *plat = dev_get_platdata(clk->dev); struct at91_pmc *pmc = plat->reg_base; enum periph_clk_type clk_type; void *addr; if (clk->id < PERIPHERAL_ID_MIN) return -1; clk_type = dev_get_driver_data(dev_get_parent(clk->dev)); if (clk_type == CLK_PERIPH_AT91RM9200) { addr = &pmc->pcer; if (clk->id > PERIPHERAL_ID_MAX) addr = &pmc->pcer1; setbits_le32(addr, PERIPHERAL_MASK(clk->id)); } else { writel(clk->id & AT91_PMC_PCR_PID_MASK, &pmc->pcr); setbits_le32(&pmc->pcr, AT91_PMC_PCR_CMD_WRITE | AT91_PMC_PCR_EN); } return 0; }
/* Test that block devices work correctly with USB */ static int dm_test_blk_usb(struct unit_test_state *uts) { struct udevice *usb_dev, *dev; struct blk_desc *dev_desc; /* Get a flash device */ state_set_skip_delays(true); ut_assertok(usb_init()); ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &usb_dev)); ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc)); /* The parent should be a block device */ ut_assertok(blk_get_device(IF_TYPE_USB, 0, &dev)); ut_asserteq_ptr(usb_dev, dev_get_parent(dev)); /* Check we have one block device for each mass storage device */ ut_asserteq(6, count_blk_devices()); /* Now go around again, making sure the old devices were unbound */ ut_assertok(usb_stop()); ut_assertok(usb_init()); ut_asserteq(6, count_blk_devices()); ut_assertok(usb_stop()); return 0; }
static int i2c_read_bytewise(struct udevice *dev, uint offset, uint8_t *buffer, int len) { struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); struct udevice *bus = dev_get_parent(dev); struct dm_i2c_ops *ops = i2c_get_ops(bus); struct i2c_msg msg[2], *ptr; uint8_t offset_buf[I2C_MAX_OFFSET_LEN]; int ret; int i; for (i = 0; i < len; i++) { if (i2c_setup_offset(chip, offset + i, offset_buf, msg)) return -EINVAL; ptr = msg + 1; ptr->addr = chip->chip_addr; ptr->flags = msg->flags | I2C_M_RD; ptr->len = 1; ptr->buf = &buffer[i]; ptr++; ret = ops->xfer(bus, msg, ptr - msg); if (ret) return ret; } return 0; }
/* Test that block device numbering works as expected */ static int dm_test_blk_devnum(struct unit_test_state *uts) { struct udevice *dev, *mmc_dev, *parent; int i; /* * Probe the devices, with the first one being probed last. This is the * one with no alias / sequence numnber. */ ut_assertok(uclass_get_device(UCLASS_MMC, 1, &dev)); ut_assertok(uclass_get_device(UCLASS_MMC, 2, &dev)); ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev)); for (i = 0; i < 3; i++) { struct blk_desc *desc; /* Check that the bblock device is attached */ ut_assertok(uclass_get_device_by_seq(UCLASS_MMC, i, &mmc_dev)); ut_assertok(blk_find_device(IF_TYPE_MMC, i, &dev)); parent = dev_get_parent(dev); ut_asserteq_ptr(parent, mmc_dev); ut_asserteq(trailing_strtol(mmc_dev->name), i); /* * Check that the block device devnum matches its parent's * sequence number */ desc = dev_get_uclass_platdata(dev); ut_asserteq(desc->devnum, i); } return 0; }
int dm_i2c_read(struct udevice *dev, uint offset, uint8_t *buffer, int len) { struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); struct udevice *bus = dev_get_parent(dev); struct dm_i2c_ops *ops = i2c_get_ops(bus); struct i2c_msg msg[2], *ptr; uint8_t offset_buf[I2C_MAX_OFFSET_LEN]; int msg_count; if (!ops->xfer) return -ENOSYS; if (chip->flags & DM_I2C_CHIP_RD_ADDRESS) return i2c_read_bytewise(dev, offset, buffer, len); ptr = msg; if (!i2c_setup_offset(chip, offset, offset_buf, ptr)) ptr++; if (len) { ptr->addr = chip->chip_addr; ptr->flags = chip->flags & DM_I2C_CHIP_10BIT ? I2C_M_TEN : 0; ptr->flags |= I2C_M_RD; ptr->len = len; ptr->buf = buffer; ptr++; } msg_count = ptr - msg; return ops->xfer(bus, msg, msg_count); }
static void spi_cs_deactivate(struct udevice *dev) { struct udevice *bus = dev_get_parent(dev); struct xilinx_spi_priv *priv = dev_get_priv(bus); struct xilinx_spi_regs *regs = priv->regs; writel(SPISSR_OFF, ®s->spissr); }
static int mmc_blk_remove(struct udevice *dev) { struct udevice *mmc_dev = dev_get_parent(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc_dev); struct mmc *mmc = upriv->mmc; return mmc_deinit(mmc); }
static int atmel_spi_release_bus(struct udevice *dev) { struct udevice *bus = dev_get_parent(dev); struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); writel(ATMEL_SPI_CR_SPIDIS, &bus_plat->regs->cr); return 0; }
static void atmel_spi_cs_deactivate(struct udevice *dev) { struct udevice *bus = dev_get_parent(dev); struct atmel_spi_priv *priv = dev_get_priv(bus); struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); u32 cs = slave_plat->cs; dm_gpio_set_value(&priv->cs_gpios[cs], 1); }
int dm_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs) { struct udevice *bus = dev_get_parent(dev); struct dm_i2c_ops *ops = i2c_get_ops(bus); if (!ops->xfer) return -ENOSYS; return ops->xfer(bus, msg, nmsgs); }
int at91_pmc_core_probe(struct udevice *dev) { struct pmc_platdata *plat = dev_get_platdata(dev); dev = dev_get_parent(dev); plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev); return 0; }
int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer, int len) { struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); struct udevice *bus = dev_get_parent(dev); struct dm_i2c_ops *ops = i2c_get_ops(bus); struct i2c_msg msg[1]; if (!ops->xfer) return -ENOSYS; if (chip->flags & DM_I2C_CHIP_WR_ADDRESS) return i2c_write_bytewise(dev, offset, buffer, len); /* * The simple approach would be to send two messages here: one to * set the offset and one to write the bytes. However some drivers * will not be expecting this, and some chips won't like how the * driver presents this on the I2C bus. * * The API does not support separate offset and data. We could extend * it with a flag indicating that there is data in the next message * that needs to be processed in the same transaction. We could * instead add an additional buffer to each message. For now, handle * this in the uclass since it isn't clear what the impact on drivers * would be with this extra complication. Unfortunately this means * copying the message. * * Use the stack for small messages, malloc() for larger ones. We * need to allow space for the offset (up to 4 bytes) and the message * itself. */ if (len < 64) { uint8_t buf[I2C_MAX_OFFSET_LEN + len]; i2c_setup_offset(chip, offset, buf, msg); msg->len += len; memcpy(buf + chip->offset_len, buffer, len); return ops->xfer(bus, msg, 1); } else { uint8_t *buf; int ret; buf = malloc(I2C_MAX_OFFSET_LEN + len); if (!buf) return -ENOMEM; i2c_setup_offset(chip, offset, buf, msg); msg->len += len; memcpy(buf + chip->offset_len, buffer, len); ret = ops->xfer(bus, msg, 1); free(buf); return ret; } }
static int xilinx_spi_release_bus(struct udevice *dev) { struct udevice *bus = dev_get_parent(dev); struct xilinx_spi_priv *priv = dev_get_priv(bus); struct xilinx_spi_regs *regs = priv->regs; writel(SPISSR_OFF, ®s->spissr); writel(XILSPI_SPICR_DFLT_OFF, ®s->spicr); return 0; }
static int pfuze100_regulator_probe(struct udevice *dev) { struct dm_regulator_uclass_platdata *uc_pdata; struct pfuze100_regulator_platdata *plat = dev_get_platdata(dev); struct pfuze100_regulator_desc *desc; switch (dev_get_driver_data(dev_get_parent(dev))) { case PFUZE100: desc = se_desc(pfuze100_regulators, ARRAY_SIZE(pfuze100_regulators), dev->name); break; case PFUZE200: desc = se_desc(pfuze200_regulators, ARRAY_SIZE(pfuze200_regulators), dev->name); break; case PFUZE3000: desc = se_desc(pfuze3000_regulators, ARRAY_SIZE(pfuze3000_regulators), dev->name); break; default: debug("Unsupported PFUZE\n"); return -EINVAL; } if (!desc) { debug("Do not support regulator %s\n", dev->name); return -EINVAL; } plat->desc = desc; uc_pdata = dev_get_uclass_platdata(dev); uc_pdata->type = desc->type; if (uc_pdata->type == REGULATOR_TYPE_BUCK) { if (!strcmp(dev->name, "swbst")) { uc_pdata->mode = pfuze_swbst_modes; uc_pdata->mode_count = ARRAY_SIZE(pfuze_swbst_modes); } else { uc_pdata->mode = pfuze_sw_modes; uc_pdata->mode_count = ARRAY_SIZE(pfuze_sw_modes); } } else if (uc_pdata->type == REGULATOR_TYPE_LDO) { uc_pdata->mode = pfuze_ldo_modes; uc_pdata->mode_count = ARRAY_SIZE(pfuze_ldo_modes); } else { uc_pdata->mode = NULL; uc_pdata->mode_count = 0; } return 0; }
static int bcm6858_led_probe(struct udevice *dev) { struct led_uc_plat *uc_plat = dev_get_uclass_platdata(dev); /* Top-level LED node */ if (!uc_plat->label) { void __iomem *regs; u32 set_bits = 0; regs = dev_remap_addr(dev); if (!regs) return -EINVAL; if (dev_read_bool(dev, "brcm,serial-led-msb-first")) set_bits |= LED_CTRL_SERIAL_LED_MSB_FIRST; if (dev_read_bool(dev, "brcm,serial-led-en-pol")) set_bits |= LED_CTRL_SERIAL_LED_EN_POL; if (dev_read_bool(dev, "brcm,serial-led-clk-pol")) set_bits |= LED_CTRL_SERIAL_LED_CLK_POL; if (dev_read_bool(dev, "brcm,serial-led-data-ppol")) set_bits |= LED_CTRL_SERIAL_LED_DATA_PPOL; if (dev_read_bool(dev, "brcm,led-test-mode")) set_bits |= LED_CTRL_LED_TEST_MODE; clrsetbits_32(regs + LED_CTRL_REG, ~0, set_bits); } else { struct bcm6858_led_priv *priv = dev_get_priv(dev); void __iomem *regs; unsigned int pin; regs = dev_remap_addr(dev_get_parent(dev)); if (!regs) return -EINVAL; pin = dev_read_u32_default(dev, "reg", LEDS_MAX); if (pin >= LEDS_MAX) return -EINVAL; priv->regs = regs; priv->pin = pin; /* this led is managed by software */ clrbits_32(regs + LED_HW_LED_EN_REG, 1 << pin); /* configure the polarity */ if (dev_read_bool(dev, "active-low")) clrbits_32(regs + LED_SW_LED_IP_PPOL_REG, 1 << pin); else setbits_32(regs + LED_SW_LED_IP_PPOL_REG, 1 << pin); } return 0; }
static int atmel_pinctrl_probe(struct udevice *dev) { struct atmel_pio4_platdata *plat = dev_get_platdata(dev); fdt_addr_t addr_base; dev = dev_get_parent(dev); addr_base = dev_get_addr(dev); if (addr_base == FDT_ADDR_T_NONE) return -EINVAL; plat->reg_base = (struct atmel_pio4_port *)addr_base; return 0; }
static int mmc_select_hwpart(struct udevice *bdev, int hwpart) { struct udevice *mmc_dev = dev_get_parent(bdev); struct mmc *mmc = mmc_get_mmc_dev(mmc_dev); struct blk_desc *desc = dev_get_uclass_platdata(bdev); if (desc->hwpart == hwpart) return 0; if (mmc->part_config == MMCPART_NOAVAILABLE) return -EMEDIUMTYPE; return mmc_switch_part(mmc, hwpart); }
static void atmel_spi_cs_deactivate(struct udevice *dev) { #ifdef CONFIG_DM_GPIO struct udevice *bus = dev_get_parent(dev); struct atmel_spi_priv *priv = dev_get_priv(bus); struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); u32 cs = slave_plat->cs; if (!dm_gpio_is_valid(&priv->cs_gpios[cs])) return; dm_gpio_set_value(&priv->cs_gpios[cs], 1); #endif }
static int mmc_blk_probe(struct udevice *dev) { struct udevice *mmc_dev = dev_get_parent(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc_dev); struct mmc *mmc = upriv->mmc; int ret; ret = mmc_init(mmc); if (ret) { debug("%s: mmc_init() failed (err=%d)\n", __func__, ret); return ret; } return 0; }
struct mmc *find_mmc_device(int dev_num) { struct udevice *dev, *mmc_dev; int ret; ret = blk_get_device(IF_TYPE_MMC, dev_num, &dev); if (ret) { #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) printf("MMC Device %d not found\n", dev_num); #endif return NULL; } mmc_dev = dev_get_parent(dev); return mmc_get_mmc_dev(mmc_dev); }
static ulong periph_get_rate(struct clk *clk) { struct udevice *dev; struct clk clk_dev; ulong clk_rate; int ret; dev = dev_get_parent(clk->dev); ret = clk_get_by_index(dev, 0, &clk_dev); if (ret) return ret; clk_rate = clk_get_rate(&clk_dev); clk_free(&clk_dev); return clk_rate; }
/** * pinctrl_config_one() - apply pinctrl settings for a single node * * @config: pin configuration node * @return: 0 on success, or negative error code on failure */ static int pinctrl_config_one(struct udevice *config) { struct udevice *pctldev; const struct pinctrl_ops *ops; pctldev = config; for (;;) { pctldev = dev_get_parent(pctldev); if (!pctldev) { dev_err(config, "could not find pctldev\n"); return -EINVAL; } if (pctldev->uclass->uc_drv->id == UCLASS_PINCTRL) break; } ops = pinctrl_get_ops(pctldev); return ops->set_state(pctldev, config); }
static int atmel_spi_claim_bus(struct udevice *dev) { struct udevice *bus = dev_get_parent(dev); struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); struct atmel_spi_priv *priv = dev_get_priv(bus); struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); struct at91_spi *reg_base = bus_plat->regs; u32 cs = slave_plat->cs; u32 freq = priv->freq; u32 scbr, csrx, mode; scbr = (priv->bus_clk_rate + freq - 1) / freq; if (scbr > ATMEL_SPI_CSRx_SCBR_MAX) return -EINVAL; if (scbr < 1) scbr = 1; csrx = ATMEL_SPI_CSRx_SCBR(scbr); csrx |= ATMEL_SPI_CSRx_BITS(ATMEL_SPI_BITS_8); if (!(priv->mode & SPI_CPHA)) csrx |= ATMEL_SPI_CSRx_NCPHA; if (priv->mode & SPI_CPOL) csrx |= ATMEL_SPI_CSRx_CPOL; writel(csrx, ®_base->csr[cs]); mode = ATMEL_SPI_MR_MSTR | ATMEL_SPI_MR_MODFDIS | ATMEL_SPI_MR_WDRBT | ATMEL_SPI_MR_PCS(~(1 << cs)); writel(mode, ®_base->mr); writel(ATMEL_SPI_CR_SPIEN, ®_base->cr); return 0; }
static int i2c_write_bytewise(struct udevice *dev, uint offset, const uint8_t *buffer, int len) { struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); struct udevice *bus = dev_get_parent(dev); struct dm_i2c_ops *ops = i2c_get_ops(bus); struct i2c_msg msg[1]; uint8_t buf[I2C_MAX_OFFSET_LEN + 1]; int ret; int i; for (i = 0; i < len; i++) { if (i2c_setup_offset(chip, offset + i, buf, msg)) return -EINVAL; buf[msg->len++] = buffer[i]; ret = ops->xfer(bus, msg, 1); if (ret) return ret; } return 0; }
static int palmas_smps_probe(struct udevice *dev) { struct dm_regulator_uclass_platdata *uc_pdata; struct udevice *parent; int idx; uc_pdata = dev_get_uclass_platdata(dev); parent = dev_get_parent(dev); int type = dev_get_driver_data(parent); uc_pdata->type = REGULATOR_TYPE_BUCK; switch (type) { case PALMAS: case TPS659038: switch (dev->driver_data) { case 123: case 12: uc_pdata->ctrl_reg = palmas_smps_ctrl[type][0]; uc_pdata->volt_reg = palmas_smps_volt[type][0]; break; case 3: uc_pdata->ctrl_reg = palmas_smps_ctrl[type][1]; uc_pdata->volt_reg = palmas_smps_volt[type][1]; break; case 45: uc_pdata->ctrl_reg = palmas_smps_ctrl[type][2]; uc_pdata->volt_reg = palmas_smps_volt[type][2]; break; case 6: case 7: case 8: case 9: case 10: idx = dev->driver_data - 3; uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx]; uc_pdata->volt_reg = palmas_smps_volt[type][idx]; break; default: printf("Wrong ID for regulator\n"); } break; case TPS65917: switch (dev->driver_data) { case 1: case 2: case 3: case 4: case 5: idx = dev->driver_data - 1; uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx]; uc_pdata->volt_reg = palmas_smps_volt[type][idx]; break; case 12: idx = 0; uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx]; uc_pdata->volt_reg = palmas_smps_volt[type][idx]; break; default: printf("Wrong ID for regulator\n"); } break; default: printf("Invalid PMIC ID\n"); } return 0; }
static int xilinx_spi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { struct udevice *bus = dev_get_parent(dev); struct xilinx_spi_priv *priv = dev_get_priv(bus); struct xilinx_spi_regs *regs = priv->regs; struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); /* assume spi core configured to do 8 bit transfers */ unsigned int bytes = bitlen / XILSPI_MAX_XFER_BITS; const unsigned char *txp = dout; unsigned char *rxp = din; unsigned rxecount = 17; /* max. 16 elements in FIFO, leftover 1 */ unsigned global_timeout; debug("spi_xfer: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", bus->seq, slave_plat->cs, bitlen, bytes, flags); if (bitlen == 0) goto done; if (bitlen % XILSPI_MAX_XFER_BITS) { printf("XILSPI warning: Not a multiple of %d bits\n", XILSPI_MAX_XFER_BITS); flags |= SPI_XFER_END; goto done; } /* empty read buffer */ while (rxecount && !(readl(®s->spisr) & SPISR_RX_EMPTY)) { readl(®s->spidrr); rxecount--; } if (!rxecount) { printf("XILSPI error: Rx buffer not empty\n"); return -1; } if (flags & SPI_XFER_BEGIN) spi_cs_activate(dev, slave_plat->cs); /* at least 1usec or greater, leftover 1 */ global_timeout = priv->freq > XILSPI_MAX_XFER_BITS * 1000000 ? 2 : (XILSPI_MAX_XFER_BITS * 1000000 / priv->freq) + 1; while (bytes--) { unsigned timeout = global_timeout; /* get Tx element from data out buffer and count up */ unsigned char d = txp ? *txp++ : CONFIG_XILINX_SPI_IDLE_VAL; debug("spi_xfer: tx:%x ", d); /* write out and wait for processing (receive data) */ writel(d & SPIDTR_8BIT_MASK, ®s->spidtr); while (timeout && readl(®s->spisr) & SPISR_RX_EMPTY) { timeout--; udelay(1); } if (!timeout) { printf("XILSPI error: Xfer timeout\n"); return -1; } /* read Rx element and push into data in buffer */ d = readl(®s->spidrr) & SPIDRR_8BIT_MASK; if (rxp) *rxp++ = d; debug("spi_xfer: rx:%x\n", d); } done: if (flags & SPI_XFER_END) spi_cs_deactivate(dev); return 0; }
static int atmel_spi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { struct udevice *bus = dev_get_parent(dev); struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); struct at91_spi *reg_base = bus_plat->regs; u32 len_tx, len_rx, len; u32 status; const u8 *txp = dout; u8 *rxp = din; u8 value; if (bitlen == 0) goto out; /* * The controller can do non-multiple-of-8 bit * transfers, but this driver currently doesn't support it. * * It's also not clear how such transfers are supposed to be * represented as a stream of bytes...this is a limitation of * the current SPI interface. */ if (bitlen % 8) { /* Errors always terminate an ongoing transfer */ flags |= SPI_XFER_END; goto out; } len = bitlen / 8; /* * The controller can do automatic CS control, but it is * somewhat quirky, and it doesn't really buy us much anyway * in the context of U-Boot. */ if (flags & SPI_XFER_BEGIN) { atmel_spi_cs_activate(dev); /* * sometimes the RDR is not empty when we get here, * in theory that should not happen, but it DOES happen. * Read it here to be on the safe side. * That also clears the OVRES flag. Required if the * following loop exits due to OVRES! */ readl(®_base->rdr); } for (len_tx = 0, len_rx = 0; len_rx < len; ) { status = readl(®_base->sr); if (status & ATMEL_SPI_SR_OVRES) return -1; if ((len_tx < len) && (status & ATMEL_SPI_SR_TDRE)) { if (txp) value = *txp++; else value = 0; writel(value, ®_base->tdr); len_tx++; } if (status & ATMEL_SPI_SR_RDRF) { value = readl(®_base->rdr); if (rxp) *rxp++ = value; len_rx++; } } out: if (flags & SPI_XFER_END) { /* * Wait until the transfer is completely done before * we deactivate CS. */ wait_for_bit(__func__, ®_base->sr, ATMEL_SPI_SR_TXEMPTY, true, 1000, false); atmel_spi_cs_deactivate(dev); } return 0; }