Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/spi/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 5 kB image not shown  

Quelle  spi-altera-core.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Altera SPI driver
 *
 * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw>
 *
 * Based on spi_s3c24xx.c, which is:
 * Copyright (c) 2006 Ben Dooks
 * Copyright (c) 2006 Simtec Electronics
 * Ben Dooks <ben@simtec.co.uk>
 */


#include <linux/errno.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spi/altera.h>
#include <linux/spi/spi.h>
#include <linux/io.h>
#include <linux/of.h>

#define DRV_NAME "spi_altera"

#define ALTERA_SPI_RXDATA 0
#define ALTERA_SPI_TXDATA 4
#define ALTERA_SPI_STATUS 8
#define ALTERA_SPI_CONTROL 12
#define ALTERA_SPI_TARGET_SEL 20

#define ALTERA_SPI_STATUS_ROE_MSK 0x8
#define ALTERA_SPI_STATUS_TOE_MSK 0x10
#define ALTERA_SPI_STATUS_TMT_MSK 0x20
#define ALTERA_SPI_STATUS_TRDY_MSK 0x40
#define ALTERA_SPI_STATUS_RRDY_MSK 0x80
#define ALTERA_SPI_STATUS_E_MSK  0x100

#define ALTERA_SPI_CONTROL_IROE_MSK 0x8
#define ALTERA_SPI_CONTROL_ITOE_MSK 0x10
#define ALTERA_SPI_CONTROL_ITRDY_MSK 0x40
#define ALTERA_SPI_CONTROL_IRRDY_MSK 0x80
#define ALTERA_SPI_CONTROL_IE_MSK 0x100
#define ALTERA_SPI_CONTROL_SSO_MSK 0x400

static int altr_spi_writel(struct altera_spi *hw, unsigned int reg,
      unsigned int val)
{
 int ret;

 ret = regmap_write(hw->regmap, hw->regoff + reg, val);
 if (ret)
  dev_err(hw->dev, "fail to write reg 0x%x val 0x%x: %d\n",
   reg, val, ret);

 return ret;
}

static int altr_spi_readl(struct altera_spi *hw, unsigned int reg,
     unsigned int *val)
{
 int ret;

 ret = regmap_read(hw->regmap, hw->regoff + reg, val);
 if (ret)
  dev_err(hw->dev, "fail to read reg 0x%x: %d\n", reg, ret);

 return ret;
}

static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev)
{
 return spi_controller_get_devdata(sdev->controller);
}

static void altera_spi_set_cs(struct spi_device *spi, bool is_high)
{
 struct altera_spi *hw = altera_spi_to_hw(spi);

 if (is_high) {
  hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
  altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
  altr_spi_writel(hw, ALTERA_SPI_TARGET_SEL, 0);
 } else {
  altr_spi_writel(hw, ALTERA_SPI_TARGET_SEL,
    BIT(spi_get_chipselect(spi, 0)));
  hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
  altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
 }
}

static void altera_spi_tx_word(struct altera_spi *hw)
{
 unsigned int txd = 0;

 if (hw->tx) {
  switch (hw->bytes_per_word) {
  case 1:
   txd = hw->tx[hw->count];
   break;
  case 2:
   txd = (hw->tx[hw->count * 2]
    | (hw->tx[hw->count * 2 + 1] << 8));
   break;
  case 4:
   txd = (hw->tx[hw->count * 4]
    | (hw->tx[hw->count * 4 + 1] << 8)
    | (hw->tx[hw->count * 4 + 2] << 16)
    | (hw->tx[hw->count * 4 + 3] << 24));
   break;

  }
 }

 altr_spi_writel(hw, ALTERA_SPI_TXDATA, txd);
}

static void altera_spi_rx_word(struct altera_spi *hw)
{
 unsigned int rxd;

 altr_spi_readl(hw, ALTERA_SPI_RXDATA, &rxd);
 if (hw->rx) {
  switch (hw->bytes_per_word) {
  case 1:
   hw->rx[hw->count] = rxd;
   break;
  case 2:
   hw->rx[hw->count * 2] = rxd;
   hw->rx[hw->count * 2 + 1] = rxd >> 8;
   break;
  case 4:
   hw->rx[hw->count * 4] = rxd;
   hw->rx[hw->count * 4 + 1] = rxd >> 8;
   hw->rx[hw->count * 4 + 2] = rxd >> 16;
   hw->rx[hw->count * 4 + 3] = rxd >> 24;
   break;

  }
 }

 hw->count++;
}

static int altera_spi_txrx(struct spi_controller *host,
 struct spi_device *spi, struct spi_transfer *t)
{
 struct altera_spi *hw = spi_controller_get_devdata(host);
 u32 val;

 hw->tx = t->tx_buf;
 hw->rx = t->rx_buf;
 hw->count = 0;
 hw->bytes_per_word = DIV_ROUND_UP(t->bits_per_word, 8);
 hw->len = t->len / hw->bytes_per_word;

 if (hw->irq >= 0) {
  /* enable receive interrupt */
  hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK;
  altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);

  /* send the first byte */
  altera_spi_tx_word(hw);

  return 1;
 }

 while (hw->count < hw->len) {
  altera_spi_tx_word(hw);

  for (;;) {
   altr_spi_readl(hw, ALTERA_SPI_STATUS, &val);
   if (val & ALTERA_SPI_STATUS_RRDY_MSK)
    break;

   cpu_relax();
  }

  altera_spi_rx_word(hw);
 }
 spi_finalize_current_transfer(host);

 return 0;
}

irqreturn_t altera_spi_irq(int irq, void *dev)
{
 struct spi_controller *host = dev;
 struct altera_spi *hw = spi_controller_get_devdata(host);

 altera_spi_rx_word(hw);

 if (hw->count < hw->len) {
  altera_spi_tx_word(hw);
 } else {
  /* disable receive interrupt */
  hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
  altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);

  spi_finalize_current_transfer(host);
 }

 return IRQ_HANDLED;
}
EXPORT_SYMBOL_GPL(altera_spi_irq);

void altera_spi_init_host(struct spi_controller *host)
{
 struct altera_spi *hw = spi_controller_get_devdata(host);
 u32 val;

 host->transfer_one = altera_spi_txrx;
 host->set_cs = altera_spi_set_cs;

 /* program defaults into the registers */
 hw->imr = 0;  /* disable spi interrupts */
 altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
 altr_spi_writel(hw, ALTERA_SPI_STATUS, 0); /* clear status reg */
 altr_spi_readl(hw, ALTERA_SPI_STATUS, &val);
 if (val & ALTERA_SPI_STATUS_RRDY_MSK)
  altr_spi_readl(hw, ALTERA_SPI_RXDATA, &val); /* flush rxdata */
}
EXPORT_SYMBOL_GPL(altera_spi_init_host);

MODULE_DESCRIPTION("Altera SPI Controller driver core");
MODULE_LICENSE("GPL");

Messung V0.5
C=96 H=90 G=93

¤ Dauer der Verarbeitung: 0.2 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.