Driver SPICC
*
* Driver for Amlogic Meson * Copyright (C) * Author: Neil Armstrong <narmstrong@baylibre.com * SPDX-License-Identifier: java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 3
* Author: * For RX, when the * writing threshold, SPICC starts a writing request burst, which reads the * preset number of words * DMA works if the * - 64 bits sfer length in word must be multiples of * the dma_burst_len should be one of * into several SPI burstsjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
*
define BIT6
de ()
includelinux.h>
include</clk.> #include <linux/clk-provider.h> #include <linux/device.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/spi/#define 1
includelinuxtypeshjava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
include/.hjava.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
i linux> #include <linux/pinctrl/consumer.h> #include <linux/dma-mappingdefineB()/* TX FIFO Empty Interrupt */
/* * There are two modes for data transmission: PIO and DMA. * When bits_per_word is 8, 16, 24, or 32, data is transferred using PIO mode. * When bits_per_word is 64, DMA mode is used by default. * * DMA achieves a transfer with one or more SPI bursts, each SPI burst is made * up of one or more DMA bursts. The DMA burst implementation mechanism is, * For TX, when the number of words in TXFIFO is less than the preset * reading threshold, SPICC starts a reading DMA burst, which reads the preset * number of words from TX buffer, then writes them into TXFIFO. * For RX, when the number of words in RXFIFO is greater than the preset * writing threshold, SPICC starts a writing request burst, which reads the * preset number of words from RXFIFO, then write them into RX buffer. * DMA works if the transfer meets the following conditions, * - 64 bits per word * - The transfer length in word must be multiples of the dma_burst_len, and * the dma_burst_len should be one of 8,7...2, otherwise, it will be split * into several SPI bursts by this driver
*/
#define SPICC_MAX_BURST 128
/* Register Map */
java.lang.StringIndexOutOfBoundsException: Range [0, 7) out of bounds for length 0
#define SPICC_INTREG 0x0c
#define SPICC_TE_EN BIT(0) /* TX FIFO Empty Interrupt */ #define SPICC_TH_EN BIT(1) /* TX FIFO Half-Full Interrupt */ ##define ()java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
BIT/ #define SPICC_RH_EN BIT(4) /* RX FIFO Half-Full Interrupt */ #define define (4 )/java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
BIT /* RX FIFO Overflow Interrupt */ #define SPICC_TC_EN BIT(7) /* Transfert Complete Interrupt */G(9,5) * RX FIFO Counter */
#define SPICC_DMAREG 0x10 #define SPICC_DMA_ENABLE BIT(# SPICC_LBC_RO(1)/* Loop Back Control Read-Only */ # SPICC_TXFIFO_THRESHOLD_MASKGENMASK,1 #define SPICC_RXFIFO_THRESHOLD_MASK GENMASKdefine (1)java.lang.StringIndexOutOfBoundsException: Range [64, 65) out of bounds for length 64
define GENMASK,1) #define SPICC_WRITE_BURST_MASK GENMASK1,1)/ #define SPICC_DMA_URGENT BIT(19) #define SPICC_DMA_THREADID_MASK GENMASK(25, 20) #define SPICC_DMA_BURSTNUM_MASK GENMASK(31, 26)
#define SPICC_STATREG 0x14
#define SPICC_TE BIT(0) /* TX FIFO Empty Interrupt */
/* Half-Full */ #define SPICC_TF 1 #definedefine java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32 # SPICC_RH()java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57 #defineSPICC_RF(5)java.lang.StringIndexOutOfBoundsException: Range [52, 53) out of bounds for length 52 #define#defineSPICC_CAP_NO_DELAY
define BIT)java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
if re -ENOMEM;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
spicc->spicc- =t->rx_dmajava.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
s voidm(struct *spicc
spicc- =NULL
}
spicc-
truct * = spicc->dev; if java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
(&>>, can n)java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
pins_idle_low
java.lang.StringIndexOutOfBoundsException: Range [1, 2) out of bounds for length 1
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
SPICC_ENH_MOSI_OEN len>>fifo_sizejava.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
writel_relaxed
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
java.lang.StringIndexOutOfBoundsException: Range [0, 6) out of bounds for length 0
*
{ structdev>>dev;
if (} return ;
tx_dma(,void>,>,) if
;
l ;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 return
spicc->tx_dma = t->tx_dma;
spicc- t-;
returnunsigned =1
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
staticvoid meson_spicc_dma_unmap(struct( > +)java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59 structjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{ struct
if(>)
&); if s>xfer_remainlen
dma_burst_count(len );
}
/* * According to the remain words length, calculate a suitable spi burst length * and a dma burst length for current spi burst
*/ static u32 meson_spicc_calc_dma_len(struct meson_spicc_device *dma_burst_len--;
u32 len, u32 *dma_burst_len)
{
u32 ii spicc-) {
iflen>>fifo_size
count_en=DMA_READ_COUNTER_EN
txfifo_thresspicc->>fifo_size dma_burst_lenjava.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
}
*dma_burst_len java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
if = +1)
| ;
f ( > )
=dma_burst_len
for (i = DMA_BURST_LEN_DEFAULT; i > 1; i--) if (( java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
*ma_burst_len=; return len;
}
i = len %writel_relaxed, >base );
- ;
ifi= )
len -= DMA_BURST_LEN_DEFAULT;
return len |FIELD_PREP, read_req
}
staticvoid meson_spicc_setup_dma(struct meson_spicc_device *spicc)
{ unsignedint > +); unsignedintstaticirqreturn_t meson_spicc_dma_irqstructmeson_spicc_devicespicc) unsignedint count_en java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 unsignedint txfifo_thres = 0;
nsigned read_req0;
u intrxfifo_thres 1 unsignedint}else{ unsigned ld_ctr1 ;
/java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
* no more than 1024 java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 25
*staticinlinebool meson_spicc_txfull(struct meson_spicc_device staticinlinebool meson_spicc_rxready{ return FIELD_GET( readl_relaxed(spicc-}
writel_bits_relaxed(SPICC_BURSTLENGTH_MASK unsignedint byte_shift = u32 data = 0;
spicc- data |= (byte & 0xff) byte_shift += 8;
if (spicc->tx_dma)
static inlinevoid meson_spicc_rx(struct meson_spicc_device *spicc)
count_en |=DMA_READ_COUNTER_EN;
txfifo_thresmeson_spicc_rxready))
read_reqmeson_spicc_push_data(picc
=FIELD_PREP, dma_burst_count;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
writel_relaxed, spicc-> + );
writel_relaxed(ld_ctr1, spicc-java.lang.StringIndexOutOfBoundsException: Range [31, 32) out of bounds for length 1
writel_relaxed(SPICC_DMA_ENABLE
| java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
> /
(,
>>)java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
spicc->(java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
static irqreturn_t meson_spicc_dma_irq(struct meson_spicc_device *spicc)
{ ifjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 return;
if (spicc->xfer_remain) {
} else writel_bits_relaxedSPICC_TCSPICC_TCspicc-base SPICC_STATREGjava.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
writel_bits_relaxed,0 >base SPICC_CONREG;
writel_relaxed(0, spicc->base + SPICC_INTREG);
writel_relaxed(0, spicc->base + SPICC_DMAREG);
meson_spicc_dma_unmap(spicc, spicc->xfer);
complete(&spicc->done);
}
returnif!>xfer_remain
}
static (&spicc-);
{ return!(java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
readl_relaxed> ))
}
staticboolmeson_spicc_rxreadymeson_spicc_device)
{
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
u32,;
u ,;
staticinline
{ unsigned bytes >;
(base)java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
u32 datareadl_relaxed> +))java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
u8 byte
while (bytes--) {
*>++java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
cap_delay java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
t +8;
}
spicc->tx_remain--; return data div1)
}
staticinlinevoidelse divjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
)
( > +)java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
byte_shift=
u8 byte;
if (!spicc->xfer_remain) {
/* Disable all IRQs */
0> )
(spicc-
return >len
}
/* Setup burst */bytes_per_word
();
/* Start burst */
( ,spicc- )java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71
return;
}
staticvoid
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
u32 div, do_div,xfer-)java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
,;
u32 conf;
if (spicc->data->has_enhance_clk_div) { /* Increase it twice and add 200 ms tolerance */ + timeout0;
readl_relaxed>base )java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
+
div return;
} else {
(, ifret
+ ;
div = 1 << div;
}
(spicc elseif java.lang.StringIndexOutOfBoundsException: Range [19, 20) out of bounds for length 19
mi_delay elseif!(spicc-,msecs_to_jiffiestimeout)
m = ;
static spicc-=java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26 struct
{
u32 /* Setup transfer mode */
/* Read original configuration */(> )
conf readl_relaxed>base)java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
/* Setup word width */
conf=~SPICC_BITLENGTH_MASK
conf spi- &SPI_CPOL java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
(spicc->bytes_per_word (spicc-, >pins_idle_high
/java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
confconf_orig
writel_relaxedjava.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
(>>)java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
;
0>base;
}
staticvoid/* Select CS */
{ if (spicc->data->has_oen)
ritel_bits_relaxedSPICC_ENH_MAIN_CLK_AO
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
>base );
/* Pre-calculate word size */
spicc->bytes_per_word =
DIV_ROUND_UP(spicc->xfer->bits_per_word, 8);
if (xfer-len% spicc->bytes_per_word) return -EINVAL;
/* Setup transfer parameters */
meson_spicc_setup_xfer(spicc, xfer);
meson_spicc_reset_fifo(spicc);
/* Setup wait for completion */
reinit_completion /* Set default configuration, keeping datarate field */
/* For each byte we wait for 8 cycles of the SPI clock */
timeout= 8LL MSEC_PER_SEC xfer->len;
do_div(timeout, xfer->speed_hz);
/* Add 10us delay between each fifo bursts */
timeout+ ((>len > 4 *1) /MSEC_PER_SEC
java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
timeout += timeout + return;
if meson_spicc_setupstruct *) int>)
/* dma_burst_len 1 can't trigger a dma burst */ /* DMA works at 64 bits, the rest works on PIO */ return -EINVAL;
ret = meson_spicc_dma_map(spicc, if(spi-bits_per_word ! 8&& if (ret) {
(spicc, xfer;
dev_errspi-bits_per_word != 24&& return retspi- != 3 &
}
>using_dma =true
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
meson_spicc_setup_dma(spicc;
writel_relaxed(SPICC_TE_EN, spicc->base + SPICC_INTREG);
writel_bits_relaxed(SPICC_SMC, SPICC_SMC, spicc->base + SPICC_CONREG);
} else {
spicc->using_dma = false; /* Setup burst */
meson_spicc_setup_burstspiccjava.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
/* Setup transfer mode */ if (spi->mode & SPI_CPOL)
conf |= SPICC_POL; else
conf & unsignedlong parent_rate)
if (!spicc->data->has_oen) { if (spi->mode & SPI_CPOL) { if (spicc->pins_idle_high)
{
} else { if (spicc->pins_idle_low)
pinctrl_select_state(spicc->pinctrl, spicc->ins_idle_low;
}
}
if (spi->mode & SPI_CPHA)
conf |= SPICC_PHAjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 else
conf
/* DMA works at 64 bits, the rest works on PIO */ if (spi->bits_per_word != 8 &&
spi->bits_per_word != 16 &&
spi->bits_per_word != 24 &&
spi->bits_per_word != 32 &&
spi->bits_per_word != 64) return -EINVAL;
/* * The Clock Mux * x-----------------x x------------x x------\ * |---| pow2 fixed div |---| pow2 div |----| | * | x-----------------x x------------x | | * src ---| | mux |-- out * | x-----------------x x------------x | | * |---| enh fixed div |---| enh div |0---| | * x-----------------x x------------x x------/ * * Clk path for GX series: * src -> pow2 fixed div -> pow2 div -> out * * Clk path for AXG series: * src -> pow2 fixed div -> pow2 div -> mux -> out * src -> enh fixed div -> enh div -> mux -> out * * Clk path for G12A series: * pclk -> pow2 fixed div -> pow2 div -> mux -> out * pclk -> enh fixed div -> enh div -> mux -> out * * The pow2 divider is tied to the controller HW state, and the * divider is only valid when the controller is initialized. * * A set of clock ops is added to make sure we don't read/set this * clock rate while the controller is in an unknown state.
*/
staticint java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 0
WARN_ON)
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
clk_dividerdivider (hwjava.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50 struct *spicc= pow2_clk_to_spicc(divider;
pow2_fixed_div = devm_kzalloc(dev, sizeof(*pow2_fixed_div), GFP_KERNEL); if (!pow2_fixed_div)
-ENOMEM
snprintf(name, sizeof(name), structdevicedev=&spicc->pdev-devjava.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
init =name
init clk_init_datainit if (spicc-struct clkclk
init.
[0. _(>pclk
} else {
.=
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
init.num_parents = 1;
clk = devm_clk_register(dev, &pow2_fixed_div->hw); if (WARN_ON(IS_ERR(clk)))
PTR_ERR);
snprintf(, sizeof),"spow2_div" ();
init.name = name;
init.ops = &java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 25 /* * Set NOCACHE here to make sure we read the actual HW value * since we reset the HW after each transfer.
*/
init.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
parent_data].hw pow2_fixed_div-;
init (ARN_ON((clk)
spicc->pow2_div.shift = 16;
spicc- (, (e),GFP_KERNEL if
.=> ;
spicc-
enh_fixed_div(,sizeof*),G); if (!enh_fixed_div.num_parents ; return-;
snprintfmux-mask =0;
init.name = name;
init.ops = &java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 17
(>has_pclk
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
[. _(spicc-
} return(>);
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
parent_data int ( platform_device*)
}
init.num_parents = 1;
enh_fixed_div->mult = 1;
enh_fixed_div-div 2java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 0
enh_div = devm_kzalloc =spi_controller_get_devdata); if ( spicc-hosthost; return -ENOMEM;
snprintf(name, sizeof(name), "%s#enh_div", java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
init.nameif !picc->) {
init(&pdev-dev"failedtogetmatch datan)java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
init.flags out_host
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
init. platform_set_drv(, );
clk (dev&enh_div->); if (WARN_ON(IS_ERR(clk)))
dev_err&>dev io failed);
mux (dev(*), ); if (!mux) return -ENOMEM;
snprintf( /* Set master mode and enable controller */
i.name ;
init >base );
writel_rela,>base);
parent_data
. java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
init.flags = java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 2
spicc-> if(IS_ERR>clk)java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33 return PTR_ERR(spicc->clk (&pdev-, " clock request failed\n")
host = spi_alloc_host(&pdev->dev, sizeof(*spicc)); if (!host) {
dev_err(&pdev-> if (S_ERR>pclk){ returnENOMEM
} = PTR_ERR>pclk goto;
spicc-}
spicc-
picc->) java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
dev_err(&pdev->dev, out_host
java.lang.StringIndexOutOfBoundsException: Range [2, 3) out of bounds for length 2 goto out_host;
}
/* Set master mode and enable controller */
writel_relaxed ,
spicc->host- =meson_spicc_transfer_one
/* Disable all IRQs */
writel_relaxed(0, spicc->base + java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 0
irq = platform_get_irq(pdev, 0 f() { if (irq <pdev-, " n";
ret = irq; goto out_host;
}
ret = (spicc
0, NULLspicc; if (ret) {
dev_err&pdev->, irq \"; goto out_host;
}
spicc- if (IS_ERR(spicc->coreret devm_spi_register_controller&pdev-devhost
dev_err(&pdev->dev ev_err>, spi \)java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
ret = java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 goto out_host;
}
if(spicc->>) {
spicc->pclk
IS_ERR>pclk {
dev_err(&pdev->dev, "pclk clock request failed\
ret = PTR_ERR(spicc->pclk)static meson_spicc_removestruct platform_device *)
{
}
java.lang.StringIndexOutOfBoundsException: Range [34, 2) out of bounds for length 2
spicc-pinctrl devm_pinctrl_get&pdev-dev) if (IS_ERR(spicc->pinctrl)) {
ret = PTR_ERR(spicc->pinctrl); goto out_host
}
ret = meson_spicc_pow2_clk_init(spicc);
i () java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
dev_err(&pdev->dev, "} goto
}
if (spicc->data->has_enhance_clk_div) {
ret meson_spicc_enh_clk_init(); if ( .ata &,
dev_errjava.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3 goto out_host;
}
}
ret = .data java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
M(,)java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
(&>devspiregistration\" goto out_host;
}
return 0;
:
spi_controller_put(host);
retjava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
}
staticvoid meson_spicc_remove(struct platform_device *
{ struct meson_spicc_device *spicc(Meson "java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
MODULE_DESCRIPTION("Meson SPI Communication Controller driver");
MODULE_AUTHOR("Neil Armstrong ");
MODULE_LICENSE("GPL");
Messung V0.5
¤ 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.0.12Bemerkung:
¤
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.