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
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.