Merge remote-tracking branch 'spi/topic/omap' into spi-next
This commit is contained in:
Коммит
1728ddb2ca
|
@ -10,7 +10,18 @@ Required properties:
|
|||
input. The default is D0 as input and
|
||||
D1 as output.
|
||||
|
||||
Example:
|
||||
Optional properties:
|
||||
- dmas: List of DMA specifiers with the controller specific format
|
||||
as described in the generic DMA client binding. A tx and rx
|
||||
specifier is required for each chip select.
|
||||
- dma-names: List of DMA request names. These strings correspond
|
||||
1:1 with the DMA specifiers listed in dmas. The string naming
|
||||
is to be "rxN" and "txN" for RX and TX requests,
|
||||
respectively, where N equals the chip select number.
|
||||
|
||||
Examples:
|
||||
|
||||
[hwmod populated DMA resources]
|
||||
|
||||
mcspi1: mcspi@1 {
|
||||
#address-cells = <1>;
|
||||
|
@ -20,3 +31,17 @@ mcspi1: mcspi@1 {
|
|||
ti,spi-num-cs = <4>;
|
||||
};
|
||||
|
||||
[generic DMA request binding]
|
||||
|
||||
mcspi1: mcspi@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "ti,omap4-mcspi";
|
||||
ti,hwmods = "mcspi1";
|
||||
ti,spi-num-cs = <2>;
|
||||
dmas = <&edma 42
|
||||
&edma 43
|
||||
&edma 44
|
||||
&edma 45>;
|
||||
dma-names = "tx0", "rx0", "tx1", "rx1";
|
||||
};
|
||||
|
|
|
@ -38,13 +38,15 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/gcd.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <linux/platform_data/spi-omap2-mcspi.h>
|
||||
|
||||
#define OMAP2_MCSPI_MAX_FREQ 48000000
|
||||
#define OMAP2_MCSPI_MAX_FIFODEPTH 64
|
||||
#define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF
|
||||
#define SPI_AUTOSUSPEND_TIMEOUT 2000
|
||||
|
||||
#define OMAP2_MCSPI_REVISION 0x00
|
||||
|
@ -54,6 +56,7 @@
|
|||
#define OMAP2_MCSPI_WAKEUPENABLE 0x20
|
||||
#define OMAP2_MCSPI_SYST 0x24
|
||||
#define OMAP2_MCSPI_MODULCTRL 0x28
|
||||
#define OMAP2_MCSPI_XFERLEVEL 0x7c
|
||||
|
||||
/* per-channel banks, 0x14 bytes each, first is: */
|
||||
#define OMAP2_MCSPI_CHCONF0 0x2c
|
||||
|
@ -63,6 +66,7 @@
|
|||
#define OMAP2_MCSPI_RX0 0x3c
|
||||
|
||||
/* per-register bitmasks: */
|
||||
#define OMAP2_MCSPI_IRQSTATUS_EOW BIT(17)
|
||||
|
||||
#define OMAP2_MCSPI_MODULCTRL_SINGLE BIT(0)
|
||||
#define OMAP2_MCSPI_MODULCTRL_MS BIT(2)
|
||||
|
@ -83,10 +87,13 @@
|
|||
#define OMAP2_MCSPI_CHCONF_IS BIT(18)
|
||||
#define OMAP2_MCSPI_CHCONF_TURBO BIT(19)
|
||||
#define OMAP2_MCSPI_CHCONF_FORCE BIT(20)
|
||||
#define OMAP2_MCSPI_CHCONF_FFET BIT(27)
|
||||
#define OMAP2_MCSPI_CHCONF_FFER BIT(28)
|
||||
|
||||
#define OMAP2_MCSPI_CHSTAT_RXS BIT(0)
|
||||
#define OMAP2_MCSPI_CHSTAT_TXS BIT(1)
|
||||
#define OMAP2_MCSPI_CHSTAT_EOT BIT(2)
|
||||
#define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3)
|
||||
|
||||
#define OMAP2_MCSPI_CHCTRL_EN BIT(0)
|
||||
|
||||
|
@ -102,6 +109,9 @@ struct omap2_mcspi_dma {
|
|||
|
||||
struct completion dma_tx_completion;
|
||||
struct completion dma_rx_completion;
|
||||
|
||||
char dma_rx_ch_name[14];
|
||||
char dma_tx_ch_name[14];
|
||||
};
|
||||
|
||||
/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
|
||||
|
@ -129,6 +139,7 @@ struct omap2_mcspi {
|
|||
struct omap2_mcspi_dma *dma_channels;
|
||||
struct device *dev;
|
||||
struct omap2_mcspi_regs ctx;
|
||||
int fifo_depth;
|
||||
unsigned int pin_dir:1;
|
||||
};
|
||||
|
||||
|
@ -187,6 +198,16 @@ static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val)
|
|||
mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
|
||||
}
|
||||
|
||||
static inline int mcspi_bytes_per_word(int word_len)
|
||||
{
|
||||
if (word_len <= 8)
|
||||
return 1;
|
||||
else if (word_len <= 16)
|
||||
return 2;
|
||||
else /* word_len <= 32 */
|
||||
return 4;
|
||||
}
|
||||
|
||||
static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
|
||||
int is_read, int enable)
|
||||
{
|
||||
|
@ -248,6 +269,58 @@ static void omap2_mcspi_set_master_mode(struct spi_master *master)
|
|||
ctx->modulctrl = l;
|
||||
}
|
||||
|
||||
static void omap2_mcspi_set_fifo(const struct spi_device *spi,
|
||||
struct spi_transfer *t, int enable)
|
||||
{
|
||||
struct spi_master *master = spi->master;
|
||||
struct omap2_mcspi_cs *cs = spi->controller_state;
|
||||
struct omap2_mcspi *mcspi;
|
||||
unsigned int wcnt;
|
||||
int fifo_depth, bytes_per_word;
|
||||
u32 chconf, xferlevel;
|
||||
|
||||
mcspi = spi_master_get_devdata(master);
|
||||
|
||||
chconf = mcspi_cached_chconf0(spi);
|
||||
if (enable) {
|
||||
bytes_per_word = mcspi_bytes_per_word(cs->word_len);
|
||||
if (t->len % bytes_per_word != 0)
|
||||
goto disable_fifo;
|
||||
|
||||
fifo_depth = gcd(t->len, OMAP2_MCSPI_MAX_FIFODEPTH);
|
||||
if (fifo_depth < 2 || fifo_depth % bytes_per_word != 0)
|
||||
goto disable_fifo;
|
||||
|
||||
wcnt = t->len / bytes_per_word;
|
||||
if (wcnt > OMAP2_MCSPI_MAX_FIFOWCNT)
|
||||
goto disable_fifo;
|
||||
|
||||
xferlevel = wcnt << 16;
|
||||
if (t->rx_buf != NULL) {
|
||||
chconf |= OMAP2_MCSPI_CHCONF_FFER;
|
||||
xferlevel |= (fifo_depth - 1) << 8;
|
||||
} else {
|
||||
chconf |= OMAP2_MCSPI_CHCONF_FFET;
|
||||
xferlevel |= fifo_depth - 1;
|
||||
}
|
||||
|
||||
mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL, xferlevel);
|
||||
mcspi_write_chconf0(spi, chconf);
|
||||
mcspi->fifo_depth = fifo_depth;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
disable_fifo:
|
||||
if (t->rx_buf != NULL)
|
||||
chconf &= ~OMAP2_MCSPI_CHCONF_FFER;
|
||||
else
|
||||
chconf &= ~OMAP2_MCSPI_CHCONF_FFET;
|
||||
|
||||
mcspi_write_chconf0(spi, chconf);
|
||||
mcspi->fifo_depth = 0;
|
||||
}
|
||||
|
||||
static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
|
||||
{
|
||||
struct spi_master *spi_cntrl = mcspi->master;
|
||||
|
@ -364,7 +437,7 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
|
|||
{
|
||||
struct omap2_mcspi *mcspi;
|
||||
struct omap2_mcspi_dma *mcspi_dma;
|
||||
unsigned int count;
|
||||
unsigned int count, dma_count;
|
||||
u32 l;
|
||||
int elements = 0;
|
||||
int word_len, element_count;
|
||||
|
@ -372,6 +445,11 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
|
|||
mcspi = spi_master_get_devdata(spi->master);
|
||||
mcspi_dma = &mcspi->dma_channels[spi->chip_select];
|
||||
count = xfer->len;
|
||||
dma_count = xfer->len;
|
||||
|
||||
if (mcspi->fifo_depth == 0)
|
||||
dma_count -= es;
|
||||
|
||||
word_len = cs->word_len;
|
||||
l = mcspi_cached_chconf0(spi);
|
||||
|
||||
|
@ -385,16 +463,15 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
|
|||
if (mcspi_dma->dma_rx) {
|
||||
struct dma_async_tx_descriptor *tx;
|
||||
struct scatterlist sg;
|
||||
size_t len = xfer->len - es;
|
||||
|
||||
dmaengine_slave_config(mcspi_dma->dma_rx, &cfg);
|
||||
|
||||
if (l & OMAP2_MCSPI_CHCONF_TURBO)
|
||||
len -= es;
|
||||
if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0)
|
||||
dma_count -= es;
|
||||
|
||||
sg_init_table(&sg, 1);
|
||||
sg_dma_address(&sg) = xfer->rx_dma;
|
||||
sg_dma_len(&sg) = len;
|
||||
sg_dma_len(&sg) = dma_count;
|
||||
|
||||
tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1,
|
||||
DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT |
|
||||
|
@ -414,6 +491,10 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
|
|||
wait_for_completion(&mcspi_dma->dma_rx_completion);
|
||||
dma_unmap_single(mcspi->dev, xfer->rx_dma, count,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
if (mcspi->fifo_depth > 0)
|
||||
return count;
|
||||
|
||||
omap2_mcspi_set_enable(spi, 0);
|
||||
|
||||
elements = element_count - 1;
|
||||
|
@ -433,10 +514,9 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
|
|||
else /* word_len <= 32 */
|
||||
((u32 *)xfer->rx_buf)[elements++] = w;
|
||||
} else {
|
||||
int bytes_per_word = mcspi_bytes_per_word(word_len);
|
||||
dev_err(&spi->dev, "DMA RX penultimate word empty");
|
||||
count -= (word_len <= 8) ? 2 :
|
||||
(word_len <= 16) ? 4 :
|
||||
/* word_len <= 32 */ 8;
|
||||
count -= (bytes_per_word << 1);
|
||||
omap2_mcspi_set_enable(spi, 1);
|
||||
return count;
|
||||
}
|
||||
|
@ -454,9 +534,7 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
|
|||
((u32 *)xfer->rx_buf)[elements] = w;
|
||||
} else {
|
||||
dev_err(&spi->dev, "DMA RX last word empty");
|
||||
count -= (word_len <= 8) ? 1 :
|
||||
(word_len <= 16) ? 2 :
|
||||
/* word_len <= 32 */ 4;
|
||||
count -= mcspi_bytes_per_word(word_len);
|
||||
}
|
||||
omap2_mcspi_set_enable(spi, 1);
|
||||
return count;
|
||||
|
@ -475,7 +553,10 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
|
|||
struct dma_slave_config cfg;
|
||||
enum dma_slave_buswidth width;
|
||||
unsigned es;
|
||||
u32 burst;
|
||||
void __iomem *chstat_reg;
|
||||
void __iomem *irqstat_reg;
|
||||
int wait_res;
|
||||
|
||||
mcspi = spi_master_get_devdata(spi->master);
|
||||
mcspi_dma = &mcspi->dma_channels[spi->chip_select];
|
||||
|
@ -493,19 +574,27 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
|
|||
es = 4;
|
||||
}
|
||||
|
||||
count = xfer->len;
|
||||
burst = 1;
|
||||
|
||||
if (mcspi->fifo_depth > 0) {
|
||||
if (count > mcspi->fifo_depth)
|
||||
burst = mcspi->fifo_depth / es;
|
||||
else
|
||||
burst = count / es;
|
||||
}
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0;
|
||||
cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0;
|
||||
cfg.src_addr_width = width;
|
||||
cfg.dst_addr_width = width;
|
||||
cfg.src_maxburst = 1;
|
||||
cfg.dst_maxburst = 1;
|
||||
cfg.src_maxburst = burst;
|
||||
cfg.dst_maxburst = burst;
|
||||
|
||||
rx = xfer->rx_buf;
|
||||
tx = xfer->tx_buf;
|
||||
|
||||
count = xfer->len;
|
||||
|
||||
if (tx != NULL)
|
||||
omap2_mcspi_tx_dma(spi, xfer, cfg);
|
||||
|
||||
|
@ -513,18 +602,38 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
|
|||
count = omap2_mcspi_rx_dma(spi, xfer, cfg, es);
|
||||
|
||||
if (tx != NULL) {
|
||||
chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
|
||||
wait_for_completion(&mcspi_dma->dma_tx_completion);
|
||||
dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (mcspi->fifo_depth > 0) {
|
||||
irqstat_reg = mcspi->base + OMAP2_MCSPI_IRQSTATUS;
|
||||
|
||||
if (mcspi_wait_for_reg_bit(irqstat_reg,
|
||||
OMAP2_MCSPI_IRQSTATUS_EOW) < 0)
|
||||
dev_err(&spi->dev, "EOW timed out\n");
|
||||
|
||||
mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS,
|
||||
OMAP2_MCSPI_IRQSTATUS_EOW);
|
||||
}
|
||||
|
||||
/* for TX_ONLY mode, be sure all words have shifted out */
|
||||
if (rx == NULL) {
|
||||
if (mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_TXS) < 0)
|
||||
dev_err(&spi->dev, "TXS timed out\n");
|
||||
else if (mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_EOT) < 0)
|
||||
chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
|
||||
if (mcspi->fifo_depth > 0) {
|
||||
wait_res = mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_TXFFE);
|
||||
if (wait_res < 0)
|
||||
dev_err(&spi->dev, "TXFFE timed out\n");
|
||||
} else {
|
||||
wait_res = mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_TXS);
|
||||
if (wait_res < 0)
|
||||
dev_err(&spi->dev, "TXS timed out\n");
|
||||
}
|
||||
if (wait_res >= 0 &&
|
||||
(mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_EOT) < 0))
|
||||
dev_err(&spi->dev, "EOT timed out\n");
|
||||
}
|
||||
}
|
||||
|
@ -830,12 +939,20 @@ static int omap2_mcspi_request_dma(struct spi_device *spi)
|
|||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
sig = mcspi_dma->dma_rx_sync_dev;
|
||||
mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
|
||||
|
||||
mcspi_dma->dma_rx =
|
||||
dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
|
||||
&sig, &master->dev,
|
||||
mcspi_dma->dma_rx_ch_name);
|
||||
if (!mcspi_dma->dma_rx)
|
||||
goto no_dma;
|
||||
|
||||
sig = mcspi_dma->dma_tx_sync_dev;
|
||||
mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
|
||||
mcspi_dma->dma_tx =
|
||||
dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
|
||||
&sig, &master->dev,
|
||||
mcspi_dma->dma_tx_ch_name);
|
||||
|
||||
if (!mcspi_dma->dma_tx) {
|
||||
dma_release_channel(mcspi_dma->dma_rx);
|
||||
mcspi_dma->dma_rx = NULL;
|
||||
|
@ -945,7 +1062,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
|
|||
cs = spi->controller_state;
|
||||
cd = spi->controller_data;
|
||||
|
||||
omap2_mcspi_set_enable(spi, 1);
|
||||
omap2_mcspi_set_enable(spi, 0);
|
||||
list_for_each_entry(t, &m->transfers, transfer_list) {
|
||||
if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
|
||||
status = -EINVAL;
|
||||
|
@ -993,6 +1110,12 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
|
|||
if (t->len) {
|
||||
unsigned count;
|
||||
|
||||
if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
|
||||
(m->is_dma_mapped || t->len >= DMA_MIN_BYTES))
|
||||
omap2_mcspi_set_fifo(spi, t, 1);
|
||||
|
||||
omap2_mcspi_set_enable(spi, 1);
|
||||
|
||||
/* RX_ONLY mode needs dummy data in TX reg */
|
||||
if (t->tx_buf == NULL)
|
||||
__raw_writel(0, cs->base
|
||||
|
@ -1019,6 +1142,11 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
|
|||
omap2_mcspi_force_cs(spi, 0);
|
||||
cs_active = 0;
|
||||
}
|
||||
|
||||
omap2_mcspi_set_enable(spi, 0);
|
||||
|
||||
if (mcspi->fifo_depth > 0)
|
||||
omap2_mcspi_set_fifo(spi, t, 0);
|
||||
}
|
||||
/* Restore defaults if they were overriden */
|
||||
if (par_override) {
|
||||
|
@ -1039,8 +1167,10 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
|
|||
|
||||
omap2_mcspi_set_enable(spi, 0);
|
||||
|
||||
m->status = status;
|
||||
if (mcspi->fifo_depth > 0 && t)
|
||||
omap2_mcspi_set_fifo(spi, t, 0);
|
||||
|
||||
m->status = status;
|
||||
}
|
||||
|
||||
static int omap2_mcspi_transfer_one_message(struct spi_master *master,
|
||||
|
@ -1177,7 +1307,6 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
|
|||
static int bus_num = 1;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
const struct of_device_id *match;
|
||||
struct pinctrl *pinctrl;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof *mcspi);
|
||||
if (master == NULL) {
|
||||
|
@ -1247,39 +1376,47 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
|
|||
goto free_master;
|
||||
|
||||
for (i = 0; i < master->num_chipselect; i++) {
|
||||
char dma_ch_name[14];
|
||||
char *dma_rx_ch_name = mcspi->dma_channels[i].dma_rx_ch_name;
|
||||
char *dma_tx_ch_name = mcspi->dma_channels[i].dma_tx_ch_name;
|
||||
struct resource *dma_res;
|
||||
|
||||
sprintf(dma_ch_name, "rx%d", i);
|
||||
dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
|
||||
dma_ch_name);
|
||||
if (!dma_res) {
|
||||
dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
|
||||
status = -ENODEV;
|
||||
break;
|
||||
}
|
||||
sprintf(dma_rx_ch_name, "rx%d", i);
|
||||
if (!pdev->dev.of_node) {
|
||||
dma_res =
|
||||
platform_get_resource_byname(pdev,
|
||||
IORESOURCE_DMA,
|
||||
dma_rx_ch_name);
|
||||
if (!dma_res) {
|
||||
dev_dbg(&pdev->dev,
|
||||
"cannot get DMA RX channel\n");
|
||||
status = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
|
||||
sprintf(dma_ch_name, "tx%d", i);
|
||||
dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
|
||||
dma_ch_name);
|
||||
if (!dma_res) {
|
||||
dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
|
||||
status = -ENODEV;
|
||||
break;
|
||||
mcspi->dma_channels[i].dma_rx_sync_dev =
|
||||
dma_res->start;
|
||||
}
|
||||
sprintf(dma_tx_ch_name, "tx%d", i);
|
||||
if (!pdev->dev.of_node) {
|
||||
dma_res =
|
||||
platform_get_resource_byname(pdev,
|
||||
IORESOURCE_DMA,
|
||||
dma_tx_ch_name);
|
||||
if (!dma_res) {
|
||||
dev_dbg(&pdev->dev,
|
||||
"cannot get DMA TX channel\n");
|
||||
status = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;
|
||||
mcspi->dma_channels[i].dma_tx_sync_dev =
|
||||
dma_res->start;
|
||||
}
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
goto dma_chnl_free;
|
||||
|
||||
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
|
||||
if (IS_ERR(pinctrl))
|
||||
dev_warn(&pdev->dev,
|
||||
"pins are not configured from the driver\n");
|
||||
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
|
Загрузка…
Ссылка в новой задаче