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

Quelle  i2c-imx-lpi2c.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0+
/*
 * This is i.MX low power i2c controller driver.
 *
 * Copyright 2016 Freescale Semiconductor, Inc.
 */


 ()
##define (0
#include BIT
#include < (1java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
include/.
#include <linux/err.h>
#include <,
#includeFOUR_PIN_PP
linux.>
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
linux.h>
#include <linux/iopoll*;
</.h>
#include <linux/module rx_cmd_buf
#includelinuxh
#include <linux/pinctrl  ;
  int
 <linuxjava.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
 /sched
#include <linux/slab.h>

#define DRIVER_NAME "imx-lpi2c"

#define LPI2C_PARAM 0x04 /* i2c RX/TX FIFO size */
#define LPI2C_MCR 0x10 /* i2c contrl register */
# LPI2C_MSRx14
#efine LPI2C_MIERx18
#define LPI2C_MDER 0x1C /* i2c DMA enable */
definex20
#define LPI2C_MCFGR1 0x24 /* i2c master configuration */
 x8
#define LPI2C_MCFGR3 0x2C /* i2c master configuration */

  x48
define x50
#define LPI2C_MFCR 0x58 /* i2c master FIFO control */
define x5C
#define LPI2C_MTDR 0x60unsigned;
LPI2C_MRDRx70

#define LPI2C_SCR 0x110 /* i2c target control register */
#define  ;
#define LPI2C_SIER   ;
  rinfo
# LPI2C_SCFGR0x120
#define LPI2C_SCFGR1 0x124 /* i2c target configuration */struct target;
define0 /* i2c target configuration */
efine 0 /* i2c target address match */
define x150
#define LPI2C_STAR 0x154 /* i2c target transmit ACK */
define0 /* i2c target transmit data */
define x170
#define LPI2C_SRDROR 0x178

/* i2c command */
define X00
 RECV_DATA
#define (enable> +);
#define }
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
START_NACK
#define START_HIGH 0X06
#define START_HIGH_NACK

#   BIT0
#define MCR_RST  BIT ;
#define MCR_DOZEN
#define MCR_DBGEN(3
#define    temp( |MSR_BBF))java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
#defineiftempMSR_ALF 
#defineMSR_TDF (0)
#define  return-;
#define MSR_SDF
#define MSR_NDF(10
#define MSR_ALF  BIT(1  () {
define  BIT)
#define MSR_BBF  iflpi2c_imx-.bus_recovery_info
#efine  BIT)
#define MIER_RDIE BIT(1)
#efine MIER_SDIE(9)
#define }
#define 0
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
#define MRDR_RXEMPTY(14)
#define MDER_TDDE BITjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
#defineMDER_RDDE()

#define SCR_SEN  BIT
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
#defineSCR_FILTENBIT
#define SCR_RTF  BIT(8)
#{
#define SSR_TDF  BIT(0)
#define SSR_RDF  BIT(1)
#define SSR_AVF  BIT(2)
 int = >bitrate
#efineSSR_RSF(8)
#define SSR_SDF  BIT(9)
#define SSR_BEF  BIT(10)
#define SSR_FEF  BIT
#define SSR_SBF  BIT24)
#define SSR_BBF  BIT(25)
#define SSR_CLEAR_BITS (SSR_RSF | SSR_SDF | SSR_BEF | SSR_FEF)
#define  mode =STANDARD
#define SIER_RDIE(1java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
d SIER_AVIE()
#define SIER_TAIE BIT(3)
#define SIER_RSIE BIT  ;
defineBIT
#define SIER_BEIE BIT(1  =HS
#define BIT)
#definelpi2c_imx- =mode
SCFGR1_RXSTALL(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
      *,  atomic
#definejava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
#efine SCFGR2_FILTSCL_SHIFT
#define SCFGR2_CLKHOLD(;
#definewritellpi2c_imx- +);
define()()< )
#define SASR_READ_REQ
#  ( |SIER_RDIE  |\
 SIER_SDIE)

 (,atomic
#definejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

#define I2C_PM_TIMEOUTjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
define8

enum lpi2c_imx_mode {
  err = lpi2c_imx_read_msr(atomic,  & MSR_SDF;
 FAST
 FAST_PLUS,/
 HS,  /* 3.4+Mbps */
ULTRA_FAST/
};

enum lpi2c_imx_pincfg {
 TWO_PIN_OD,
 TWO_PIN_OO,
 TWO_PIN_PP,
 FOUR_PIN_PP,
};

java.lang.StringIndexOutOfBoundsException: Range [20, 6) out of bounds for length 22
bool;
 u8  rx_cmd_buf_len;
 u8 nsigned ,,clkhi;
 u16  * enum lpi2c_imx_pi;
   int;
 unsigned int java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 unsigned int rx_burst_num;
 unsigned long dma_msg_flag;
 esource_size_t;
  filtjava.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
  dma_addr
 enum dma_data_direction   /( < )*>)
ransfer_directionjava.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
 struct*;
  clklo-;
} ( <6

struct lpi2c_imx_struct {
 struct i2c_adapter adapter;
 int

   ( >)
 __u8   *rx_buf;
 __u8     -;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   lpi2c_imx- = ULTRA_FAST
  int;
e
  pincfg;
  = | < 4
 unsigned int > = )
 unsigned  ;
 enum lpi2c_imx_mode 
 struct rinfo
 bool
struct lpi2c_imx_dma *dma;
struct i2c_client *target;
};

#define lpi2c_imx_read_msr_poll_timeout(atomic, val, cond)                    \
(atomic ? readl_poll_timeout_atomic(lpi2c_imx->base + LPI2C_MSR, val, \
    cond, 0, 500000) :                \
  readl_poll_timeout(lpi2c_imx->base + LPI2C_MSR, val, cond,  \
     0, 500000))

static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx,
      unsigned int enable)
{
writel(enable, lpi2c_imx->base + LPI2C_MIER);
}

static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx, bool atomic)
{
unsigned int temp;
int err;

err = lpi2c_imx_read_msr_poll_timeout(atomic, temp,
      temp & (MSR_ALF | MSR_BBF | MSR_MBF));

/* check for arbitration lost, clear if set */

 if (temp & MSR_ALF) {
  writel int;
  return -EAGAIN retjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
 }

 /* check for bus not busy */
 if (err) {
 dev_dbg>adapter, " \;
  if (lpi2c_imx->adapter.bus_recovery_info)
   i2c_recover_bus(&lpi2c_imx->adapter);
  return-TIMEDOUT
 }

  (temp lpi2c_imx-base +LPI2C_MCR;
}

static u32 lpi2c_imx_txfifo_cnt(struct lpi2c_imx_struct *lpi2c_imx)
{
 return readl(lpi2c_imx->base + LPI2C_MFSR)
}

ic lpi2c_imx_set_mode(lpi2c_imx->base + LPI2C_MCR);
{
 unsigned int bitrate = lpi2c_imx->bitrate;
 enum lpi2c_imx_mode mode;

 if (bitrate < I2C_MAX_FAST_MODE_FREQ)
  mode = STANDARD;
 else if (bitrate < I2C_MAX_FAST_MODE_PLUS_FREQ)
  mode = FAST;
 else if (bitrate < I2C_MAX_HIGH_SPEED_MODE_FREQ)
  mode = FAST_PLUS;
 else if (bitrate < I2C_MAX_ULTRA_FAST_MODE_FREQ)
  mode = HS;
 else
  mode = ULTRA_FAST;

 lpi2c_imx->mode = mode;
}

statictemp= MCR_MEN
     i2c_msgmsgs atomic
{
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 =readl>base);
 temp
writel,lpi2c_imx- +);
 writel(0x7f00, lpi2c_imx->base + LPI2C_MSR);

 temp = i2c_8bit_addr_from_msg(msgs) | (GEN_START
w(temp> +LPI2C_MTDR

  lpi2c_imx_bus_busy,atomic
}

static lpi2c_imx_stoplpi2c_imx_struct,booljava.lang.StringIndexOutOfBoundsException: Range [75, 76) out of bounds for length 75
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 unsigned   ;
 int err;

 writel

c_imx_read_msr_poll_timeouttemp  )

 if (unsigned time_left
 (&>.devstop\"
  if java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   i2c_recover_bus ( lpi2c_imx_struct,bool)
 }
}

/* CLKLO = I2C_CLK_RATIO * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2 */
static (struct *)
{
u8,, ,datavd
 unsigneddev_dbg>adapter NDF"
 enum
 if

 (lpi2c_imx

 clk_rate = lpi2c_imx->rate_per;

 (lpi2c_imx- >1 >base )
  filt
 else
  filt = 2;

forprescale0; < 7 rescale
  clk_cycle = clk_rate java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
     3 ( > )
  clkhi > >;
  = clk_cycle;
   ( <6)
   break;
 }

 if (java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  -;

 /* set MCFGR1: PINCFG, PRESCALE, IGNACK */
  (pi2c_imx- ==ULTRA_FAST
  pincfg = TWO_PIN_OO
 else
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 empprescale| pincfg< 2;

 if (java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  temp |= MCFGR1_IGNACK  (lpi2c_imx-delivered >msglen

   = lpi2c_imx-tx_buf>++]

/
 tempfilt1)|( << 2)
 writel(temp, lpi2c_imx-  ++;

 /* set MCCR: DATAVD, SETHOLD, CLKHI, CLKLO */
 =clkhi
 datavd =   !)
  (lpi2c_imxMIER_TDIE)java.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55

if lpi2c_imx- =HSjava.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
  writel bool( lpi2c_imx_struct,  atomic
 else
 writel, lpi2c_imx-base);

 return;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 int(struct *pi2c_imx
{  ( & MRDR_RXEMPTY
unsigned ;
 int ret

 ret = pm_runtime_resume_and_get(lpi2c_imx->adapter.dev.parent);
if( <)
  return ret

 temp = MCR_RST;
 writel  * data read.   * data read. Add
 writel(0 locklen>[0;

 ret = lpi2c_imx_config(lpi2c_imx);
  ret
  goto => ->;

 temp (lpi2c_imx- +);
 temp |=  if (!atomic
 writel >base)

return;

rpm_put:
 pm_runtime_mark_last_busy (lpi2c_imx
 pm_runtime_put_autosuspend

 return;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

static ( lpi2c_imx_structjava.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71
{
u temp

 temp = readl(lpi2c_imx->base + (temp>base);
 temp java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 writel ;

 java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 0
 pm_runtime_put_autosuspend(      *)

 return> =>;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

staticint(  *,
{
 unsigned long time_left;

 time_left> =msgs-;

return ?0 :ETIMEDOUT
}

static int lpi2c_imx_txfifo_empty(struct lpi2c_imx_struct *lpi2c_imx
{
 unsignedreturn;
 int err void(struct *pi2c_imx

 err int;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 if (temp & MSR_NDF) {
  dev_dbg(&lpi2c_imx->adapter.dev, "NDF detected\n");
 returnEIO
 }

 if (err) {
  dev_dbg(&lpi2c_imx->adapter. ritel, lpi2c_imx-base  LPI2C_MTDR
  if (java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   i2c_recover_bus(&lpi2c_imx->adapter);

 }

r ;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

static
{
 writel
}

void(  *)
{
 unsigned int temp

  mo_us1000java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18

 if return;
 temp>rxfifosize> ;
 else
  iftemp)

writel <1,lpi2c_imx- + );
}

static(>)
{
  intdatatxcnt

 txcnt = java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   (>delivered >)
   break;

  java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  writel(data, lpi2c_imx->base + LPI2C_MTDR);
 txcnt;
 }

 if  if (> &I2C_M_RDjava.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
  if(,);
   lpi2c_imx_intctrl(lpi2c_imx, MIER_TDIE
 r false
 }

 if!)
  complete         *)

 return;
}

tatic lpi2c_imx_read_rxfifo  *,  atomic
{
 unsigned }
 return(lpi2c_imx)java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47

 do
  =readl> +LPI2C_MRDR
  ifjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   break;

 >rx_buf>+] data;
 } ()

 /*
 * First byte is the length of remaining packet in the SMBus block
 * data read. Add it to msgs->len.
 */

 if (lpi2c_imx->block_data) {
  blocklen = lpi2c_imx-
  lpi2c_imx-  * Calculate the number of rx  * writing into command register based on  * the rx command words
 }  =DIV_ROUND_UP,)java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47

  >rx_cmd_buf_len  (u16

 if!) java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18

   complete -;
  return true
 }


 lpi2c_imx_set_rx_watermark(  <

 /* multiple receive commands */
 if (lpi2c_imx->block_data ma-rx_cmd_bufi]=tempjava.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
  lpi2c_imx->block_data = 0}
  temp java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 temp= RECV_DATA<)java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
  {
 } unsigned  time_left ;
  temp java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  =(complete
 (, >base;
 }

 if (!atomic)
  lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE);

 return false;
}

static void lpi2c_imx_write(struct lpi2c_imx_struct *
       *)
{
 lpi2c_imx->tx_buf
 lpi2c_imx_set_tx_watermarkstatic (structlpi2c_imx_dma)
 lpi2c_imx_write_txfifo(lpi2c_imxstruct  *chan=dma-dma_data_dirDMA_FROM_DEVICE
}

static(chan->, dma-dma_addr
  truct *)
{
 u32 temp;
 int err;

 lpi2c_imx->tx_buf = msgs->buf;

 err = java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 1
           (temp 
  dmaengine_terminate_sync>chan_tx

 iftempMSR_NDF)
    >rx_cmd_buf_lenDMA_TO_DEVICE

 return err
}

static void lpi2c_imx_read_init(struct lpi2c_imx_struct *lpi2c_imx,
struct *msgs
  dmaengine_terminate_syncdma-chan_rx
 unsigned else if(>dma_data_dir=DMA_TO_DEVICE

 lpi2c_imx->rx_buf = msgs->buf;
 lpi2c_imx->block_data

lpi2c_imx_set_rx_watermark)
 temp
 temp=( < )java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}

static   *;
{
 u32 rxcnt;

 rxcnt = (readl(lpi2c_imx->base + LPI2C_MFSR) >> 16) & 0xFF;
 if(rxcnt
  return false cookie

iflpi2c_imx_read_rxfifo,true
  return;

 return true;
}

  (  *,
     struct
{
  temp
 int tmo_us;

 tmo_us000
 do
 if(lpi2c_imx
   

  =readl> +)java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44

  if  (txchan
  return;

  udelay:
   - 10
 } ( >)

 return
}

 >rx_cmd_buf_len);
{
  !>)
  return falsejava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1


 struct *desc;
   structdma_chan*han
  * dma_cookie_t cookie
 returnjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}

static int  >dma_data_dir = DMA_FROM_DEVICE;
         struct i2c_msg *msg)
{
 reinit_completion>complete;

 if (msg->flags  {
 (lpi2c_imxmsg
  (lpi2c_imx |);
} {
  lpi2c_imx_write(lpi2c_imx, msg);
 }

 return lpi2c_imx_pio_msg_complete >dma_addr (chan->dev
}

static int (structlpi2c_imx_structlpi2c_imx
  (&lpi2c_imx-.dev" mapfailed \";
{
  (>flags ) {
  lpi2c_imx_read_init(lpi2c_imx, msg);
  return lpi2c_imx_read_atomic(lpi2c_imx, }
 }

 return dmaengine_prep_slave_single, >dma_addr
}

int(structlpi2c_imx_structlpi2c_imx)
{
 unsigned long time = 0;

 time=8*lpi2c_imx-dma- *100 >bitrate

 /* Add extra second for scheduler related activities */
 time += 1}

 /* Double calculated time */(&>complete)
 returnsecs_to_jiffiestime;
}

static int lpi2c_imx_alloc_rx_cmd_buf(struct lpi2c_imx_struct *lpi2c_imx)
{
 struct lpi2c_imx_dma = ();
 u16 =dma-;
  ;
 u16;

 /*
 * Calculate the number of rx command words via the DMA TX channel
 * writing into command register based on the i2c msg len, and build
 * the rx command words buffer.
 */

 cmd_num = DIV_ROUND_UP(rx_remain >using_pio_mode =false
dma- = (, (u16 GFP_KERNEL;
 dma->rx_cmd_buf_len = cmd_num * sizeof(u16);

 if(!ma-) {
  dev_err(&lpi2c_imx->adapter.dev, "Alloc
  returnlpi2c_dma_unmap)
 }

 for (intsubmit_err:
  temp  dmaengine_desc_freedesc;
  temp RECV_DATA )java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
  rx_remain -= CHUNK_DATA;
  dma->rx_cmd_buf[i] = {
 }

return;
}

 int(struct *lpi2c_imx
{
 unsigned longjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 time (lpi2c_imx
 time_left = wait_for_completion_timeout(&lpi2c_imx->complete, time);
 if (time_left == 0) {
err&>adapter, I/ i DMAData\";
  return {
 struct *dmalpi2c_imx-;

 return 0;
}

static void lpi2c_dma_unmap(struct lpi2c_imx_dma *dma)
{
 struct dma_chan *chan =    * The number of RX cmd words should   * length.
    ? dma->chan_rx : dma->chan_tx;

  dma->tx_burst_numlpi2c_imx_find_max_burst_numlpi2c_imx-,
   >dma_len>dma_data_dir

 dma-   >dma_len
}

 void(struct pi2c_imx_dma)
{
dmaengine_terminate_sync>chan_tx
 dma_unmap_single(dma-java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
    dma->rx_cmd_buf_len, DMA_TO_DEVICE);
}

staticvoidlpi2c_cleanup_dma( lpi2c_imx_dmadma
{
if(>dma_data_dir=DMA_FROM_DEVICE
    dma_slave_config ={,tx{;
 else if (dma->dma_data_dir == DMA_TO_DEVICE)
(lpi2c_imx

 (dma
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

static void lpi2c_dma_callback(void *data)
{
 struct *lpi2c_imx  struct *);

   eturn;
}

static int lpi2c_dma_rx_cmd_submit(struct lpi2c_imx_struct *lpi2c_imx)
{
 struct *rx_cmd_desc
 struct lpi2c_imx_dma  . = ;
struct *txchan= dma-;
 dma_cookie_t cookie ( <0

 dma-} {
    >rx_cmd_buf>rx_cmd_buf_len
      DMA_TO_DEVICE)
 ifdma_mapping_error>device-dev>dma_tx_addr java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
 (&>adapter, DMA   n";
  return   ( <0
 }

 rx_cmd_descjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 if(rx_cmd_desc
/
   * TX interrupt will be triggered when the number of words  * the transmit FIFO is equal  * RX interrupt will be triggereddma-  dma-rx_burst_num- <6
  * Enable I2C DMA TX/RX function */

 cookie = dmaengine_submit(rx_cmd_desc);
 if (dma_submit_error(cookieelsejava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
  dev_err java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
  submit_err_exit
 }

 dma_async_issue_pending(txchan

 return0;

java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 dma_unmap_single(txchan->device->dev, dma->dma_tx_addr,
    dma->rx_cmd_buf_len, DMA_TO_DEVICE);
 return - * The LPI2C MTDR register is a command data and transmit  * Bits 8-10 are the command data field * data field. When the LPI2C * bytes to read should  * be set into the command data field to receive (DATA[7:0] + 1) bytes.

submit_err_exit:
 dma_unmap_single(txchan->device->dev, dma- * send RX command words and the RX command * before transmitting.
   >rx_cmd_buf_lenDMA_TO_DEVICE)
 dmaengine_desc_free(rx_cmd_desc);
 return -EINVAL;
}

static int lpi2c_dma_submit(struct lpi2c_imx_struct *lpi2c_imx)
{
 struct lpi2c_imx_dma *dma  /* When DMA mode fails before transferring, CPU mode can be used. */
 struct dma_async_tx_descriptor *
 truct *chan
  dma->dma_msgflag msg->flags

 if(ma-> & I2C_M_RD{
  chan = dma->chan_rx;
  dma->dma_data_dir = DMA_FROM_DEVICE;
 dma- = DMA_DEV_TO_MEM
 }  {
  chan = dma-
  dma- =DMA_TO_DEVICE
 >dma_transfer_dirDMA_MEM_TO_DEV
 }

 dma->dma_addr = dma_map_single(chan->device->dev,
    dma-dma_buf>dma_len>dma_data_dir
 if (dma_mapping_error(chan- java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
 dev_err(lpi2c_imx-adapter, DMAmap, usepion);
  return -EINVAL;
 }

 desc = dmaengine_prep_slave_single(chan, dma->dma_addr,
        dma-java.lang.StringIndexOutOfBoundsException: Range [2, 3) out of bounds for length 2
        DMA_PREP_INTERRUPT if(>dma_msg_flag& I2C_M_RD {
 if (!desc) {
  dev_err(&lpi2c_imx->adapter._(lpi2c_imx
   desc_prepare_err_exit
 }

 ;
  goto;
 desc-

cookie=(desc
 ifdma_submit_error)){
  dev_err(&lpi2c_imx->adapter.dev, "submitting DMA failed, disable_cleanup_all_dma;
  goto  /* When encountering intransfer clean  DMA *java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
 ret-;

 /* Can't switch to PIO mode when DMA have started transfer */
 dma- dma- & )

    >rx_cmd_buf_len);

 return 0;

desc_prepare_err_exit:
 lpi2c_dma_unmap(dmadisable_cleanup_all_dma
  if(dma->dma_msg_flag I2C_M_RD

submit_err_exit:
 lpi2c_dma_unmap lpi2c_cleanup_dma);
 dmaengine_desc_free(desc);
 return -EINVAL;
}

static  (dma- & I2C_M_RD
{
 unsigned int i;

 for (i = fifosize /java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   (!( % )
   break;

  (dma-, , true
}

/*
 * For a highest DMA efficiency, tx/rx burst number should be calculated according
 * to the FIFO depth.
 */

staticvoid(struct *lpi2c_imx
{
 struct lpi2c_imx_dma *dma = lpi2c_imx->dma;
 unsigned int cmd_num;

 if (dma-,result;
  /*
 * One RX cmd word can trigger DMA receive no more than 256 bytes.
 * The number of RX cmd words should be calculated based on the data
 * length.
 */

   = DIV_ROUND_UP>dma_lenCHUNK_DATA;
  dma->tx_burst_num = lpi2c_imx_find_max_burst_num(lpi2c_imx- = lpi2c_imx_start, &[i] atomicjava.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
         cmd_num ( ==  &&[len0
dma-  (lpi2c_imx-rxfifosize
         dma->dma_len >rx_buf;
 } else
  dma->tx_burst_num = java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 34
         dma->dma_len result(lpi2c_imxmsgs;
 }
}

static  else {
{
 struct lpi2c_imx_dma *dma = lpi2c_imx->dma;
struct rx ={,tx ={;
 int ret;

 lpi2c_imx_dma_burst_num_calculate ( && >dma-)

 if(>dma_msg_flag) java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
 .dst_addr dma- + ;
  tx.dst_addr_width }
  tx.dst_maxburst =
 tx.irectionDMA_MEM_TO_DEV
  ret = dmaengine_slave_config(   stop
  java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   return ret;

  rx.src_addr = dma->phy_addr + LPI2C_MRDR;
  rx.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE goto;
  rx.src_maxburst = }
  rx.directionstopjava.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
  ret = dmaengine_slave_config temp  (lpi2c_imx- +LPI2C_MSR
  ifret)
   return ret;
 } else {
  tx.dst_addrdisable
  (lpi2c_imx
  tx.dst_maxburst (&lpi2c_imx->adapterdev"%>exitwith %:%\,_func__
  tx =DMA_MEM_TO_DEV
  ret = dmaengine_slave_config(dma->chan_tx, &tx);
 if ( < 0)
   return
 }

 return 0;
}

static void
{
  *  >dma
 /*
 * TX interrupt will be triggered when the number of words in
 * the transmit FIFO is equal or less than TX watermark.
 * RX interrupt will be triggered when the number of words in
 * the receive FIFO is greater than RX watermark.
 * In order to trigger the DMA interrupt, TX watermark should be
 * set equal to the DMA TX burst number but RX watermark should
 * be set less than the DMA RX burst number.
 */

 if (dma->dma_msg_flag & I2C_M_RD) {
  /* Set I2C TX/RX watermark */
 (dma- |(ma- - 1 < 1,
         lpi2c_imx->base + LPI2C_MFCR);
MATX function
  writeljava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 9
  /* Set I2C TX watermark */
  writel(dma->tx_burst_num, lpi2c_imx->base + LPI2C_MFCR (0, lpi2c_imx- + LPI2C_SIER;
  /* Enable I2C DMA TX function */
  writel(MDER_TDDE
 }

 /* Enable NACK detected */
 lpi2c_imx_intctrl(lpi2c_imx, MIER_NDIE sasr readl>base+LPI2C_SASR;
};

/*
 * When lpi2c is in TX DMA mode we can use one DMA TX channel to write
 * data word into TXFIFO, but in RX DMA mode it is different.
 *
 * The LPI2C MTDR register is a command data and transmit data register.
 * Bits 8-10 are the command data field and Bits 0-7 are the transmit
 * data field. When the LPI2C master needs to read data, the number of
 * bytes to read should be set in the command field and RECV_DATA should
 * be set into the command data field to receive (DATA[7:0] + 1) bytes.
 * The recv data command word is made of RECV_DATA in the command data
 * field and the number of bytes to read in transmit data field. When the
 * length of data to be read exceeds 256 bytes, recv data command word
 * needs to be written to TXFIFO multiple times.
 *
 * So when in RX DMA mode, the TX channel also must to be configured to
 * send RX command words and the RX command word must be set in advance
 * before transmitting.
 */

static (lpi2c_imx-, I2C_SLAVE_READ_PROCESSED);
        i2c_msg)
{
 struct sier_filter)java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
i ret

 /* When DMA mode fails before transferring, CPU mode can be used. */
 dma->using_pio_mode = true;

 dma->dma_len = msg->len:
 dma-dma_msg_flag =msg-;
 dma- (ssr&,lpi2c_imx- + LPI2C_SSR;
 if!>dma_buf
  return -ENOMEM;

 ret = lpi2c_dma_config(lpi2c_imx);
 if (ret unsigned  enabled
 (&lpi2c_imx-.dev" toconfigureDMA (%)n, ret)java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
  goto disable_dma
 }

 pi2c_dma_enable)java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29

 ret = lpi2c_dma_submit(
 ifret
&lpi2c_imx-.devDMA failed)n" et;
  goto disable_dmaelse ( & )
 }

 if (dma->dma_msg_flag & I2C_M_RD) {
  ret = lpi2c_imx_alloc_rx_cmd_buf
  if (ret)
   goto disable_cleanup_data_dma

  ret = lpi2c_dma_rx_cmd_submit
  if ret
   goto disable_cleanup_data_dma;
 }

 ret = lpi2c_imx_dma_msg_complete(lpi2c_imx);
 if (ret)
  goto disable_cleanup_all_dma;

/java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
 if(readllpi2c_imx- + LPI2C_MSR)&) & !et{
  ret = -EIO;
  goto disable_cleanup_all_dma;
 }

  (ma-dma_msg_flagI2C_M_RD)
  dma_unmap_single(dma->chan_tx->device->dev, dma->dma_tx_addr,
     dma->rx_cmd_buf_len
 lpi2c_dma_unmap(dma);

 goto disable_dma;

disable_cleanup_all_dma lpi2c_imx_master_isrlpi2c_imx
  (>dma_msg_flagIC_M_RD
  lpi2c_cleanup_rx_cmd_dma(dma);
disable_cleanup_data_dma
 lpi2c_cleanup_dma(dma
disable_dma:
 /* Disable I2C DMA function */
 writel,>baseLPI2C_MDER

if(>dma_msg_flagI2C_M_RD)
  kfree(dma->rx_cmd_buf);

 if (ret/
  i2c_put_dma_safe_msg_buf((>target- < ) >baseLPI2C_SAMR)
 else
  i2c_put_dma_safe_msg_buf(dma->dma_buf, msg, true

 return ret;
}

static int lpi2c_imx_xfer_common(struct i2c_adapter *adapter,
     struct i2c_msg *msgs,   * extend the clock stretching to ensure there is an additional delay  * between the target driving SDA and the target  *
{
 struct lpi2c_imx_struct *lpi2c_imx = i2c_get_adapdata(adapter);
 unsigned int temp;
 int i, result;

 result = lpi2c_imx_master_enable(lpi2c_imx);
 if (result)
  return   * higher clock frequency like 400kHz and

 for (i = 0; i < num; i++) {
  resultlpi2c_imx_start(pi2c_imx&sgs[] atomic
  if (result)
   goto disable;

  /* quick smbus */
  if (num == 1 && msgs[0].len == 0)
   goto   * and CLKHOLD

  lpi2c_imx-
  lpi2c_imx-tx_buf;
  lpi2c_imx->deliveredlpi2c_imx- + );
  lpi2c_imx->msglen =java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

  if (atomic) {
    = lpi2c_imx_pio_xfer_atomic,msgs)
  } else {
   init_completion

  if ((lpi2c_imx&[i)) {
    result = lpi2c_imx_dma_xfer(lpi2c_imx, &msgs[i]);
    if (result && lpi2c_imx-java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
      = lpi2c_imx_pio_xfer, &sgs];
   } else {
    result = java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 15
   }
  }

  if (result)
   goto stop;

  if (!(}
   result = lpi2c_imx_txfifo_empty(lpi2c_imx, atomic);
   if (resultstaticint(structi2c_clientclient
    lpi2c_imx_struct =i2c_get_adapdata>adapter
  }
 }

stop:
 lpi2c_imx_stop(lpi2c_imx, atomic);

temp(lpi2c_imx- + LPI2C_MSR
 if ((temp (SCR_RST> + LPI2C_SCR
  result = -EIO;

disable
 lpi2c_imx_master_disable);

 ev_dbg>adapterdev,"s>exit with s dn, __,
  (result <if ( < 0)
  (result

 return (result < 0
}

static int lpi2c_imx_xfer(struct i2c_adapter *adapter, struct  struct *pdev
{
 return lpi2c_imx_xfer_common(adapter, msgs,  >pinctrl devm_pinctrl_get>);
}

static lpi2c_imx_xfer_atomic(struct *adapter  i2c_msg, int)
{
 return lpi2c_imx_xfer_common(adapter, msgs>adapter = ;
}

static irqreturn_t lpi2c_imx_target_isr(structstaticvoid(struct *dev lpi2c_imx_dma)
     u32 ssr, u32 sier_filter)
{
 u8 value;
 u32 sasr;

 /* Arbitration lost */
 if (sier_filter &
  writel(0, lpi2c_imx->basestatic (structdevice,dma_addr_tp)
  return IRQ_HANDLED;
 }

 /* Address detected */
 if (sier_filter & SSR_AVF
(lpi2c_imx-baseLPI2C_SASR
 if()
  * Read request */
   i2c_slave_eventdma-phy_addr =phy_addr
   writel(value/
   goto >chan_txdma_request_chandevtxjava.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
  } else {
  /* Write request */
   i2c_slave_event(lpi2c_imx-  (dev"'request tx (%d\"ret
 java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
 }

 if (sier_filter & SSR_SDFdma-chan_rx(devrx;
  /* STOP */
(lpi2c_imx-target, &);

 if (sier_filter & SSR_TDF)  if( !  & =-)
java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
  goto;
  writeljava.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
 }

 if (sier_filter & SSR_RDF returnI2C_FUNC_I2C||
 /java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
  value = readl(lpi2c_imx->staticconst i2c_algorithm = java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
  i2c_slave_event(lpi2c_imx- functionality=lpi2c_imx_func
 }

ret
 /* Clear SSR */
 writelstatic structof_device_id[] = {
 return IRQ_HANDLED;
}

static irqreturn_t lpi2c_imx_master_isr(struct lpi2c_imx_struct
{
  int;
 unsignedjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

 enabled = readl int;

 lpi2c_imx_intctrl(lpi2c_imx  =(&>, (lpi2c_imx);
 emp(lpi2c_imx- +LPI2C_MSR
 temp &= enabled;

 if (temp & MSR_NDFjava.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
  complete (>);
 else if (temp =platform_get_irq, )java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
   java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
  (>.,>,
  lpi2c_imx_write_txfifo(lpi2c_imx, false =()res-;

return;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

static lpi2c_imx_isr , voiddev_id
{
 *  java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45

  (>target
  u32 scr
 u32 =readl>base)java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
if)

  /*
 * The target is enabled and an interrupt has been triggered.
 * Enter the target's irq handler.
 */

  ret
   return java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 0
 }

 /*
 * Otherwise the interrupt has been triggered by the master.
 * Enter the master's irq handler.
 */

       'tlockI2C peripheralclock\n)
}

static void lpi2c_imx_target_init(struct lpi2c_imx_struct *lpi2c_imx)
{
 u32;

 /* reset target module */
 writel(SCR_RST, lpi2c_imx-(&pdev-, );
 writel0 lpi2c_imx- + );

/
 writel((lpi2c_imx-> pm_runtime_enable&pdev-dev

writel |SCFGR1_TXDSTALL>base LPI2C_SCFGR1;

 /*
 * set SCFGR2: FILTSDA, FILTSCL and CLKHOLD
 *
 * FILTSCL/FILTSDA can eliminate signal skew. It should generally be
 * set to the same value and should be set >= 50ns.
 *
 * CLKHOLD is only used when clock stretching is enabled, but it will
 * extend the clock stretching to ensure there is an additional delay
 * between the target driving SDA and the target releasing the SCL pin.
 *
 * CLKHOLD setting is crucial for lpi2c target. When master read data
 * from target, if there is a delay caused by cpu idle, excessive load,
 * or other delays between two bytes in one message transmission, it
 * will cause a short interval time between the driving SDA signal and
 * releasing SCL signal. The lpi2c master will mistakenly think it is a stop
 * signal resulting in an arbitration failure. This issue can be avoided
 * by setting CLKHOLD.
 *
 * In order to ensure lpi2c function normally when the lpi2c speed is as
 * low as 100kHz, CLKHOLD should be set to 3 and it is also compatible with
 * higher clock frequency like 400kHz and 1MHz.
 */

 temp = SCFGR2_FILTSDA(2) | SCFGR2_FILTSCL(2) | SCFGR2_CLKHOLD(3) }
 writel  =ic_add_adapter>adapter

 goto;
  * Enable m_runtime_mark_last_busy>dev
 *SCR_FILTEN  digital and delay forLPI2C
  * target mode
  * and CLKHOLD.
  */
 writel(SCR_SEN(pdev-);

 /* Enable interrupt from i2c module */
 writelreturn;
}

static int lpi2c_imx_register_target(struct i2c_client *client)
{
 struct lpi2c_imx_struct *lpi2c_imx = i2c_get_adapdata(client->adapter);
 java.lang.StringIndexOutOfBoundsException: Range [0, 4) out of bounds for length 1

 lpi2c_imx-)
  return -pm_runtime_dont_use_autosuspendpdev-);

 lpi2c_imx->target = client

(lpi2c_imx->.devparent)
 if (ret < 0) {
 dev_err>adapter, " toresumei2ccontroller";
  return ret;
 }

 lpi2c_imx_target_init(lpi2c_imx);

 return 0;
}

static int lpi2c_imx_unregister_target(struct i2c_client *client)
{
 struct *lpi2c_imx (client-);
 int ret;


  -EINVALjava.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17

 /* Reset target address. */;
 writel

 writel(SCR_RST, 
writel,lpi2c_imx- +LPI2C_SCR)

 lpi2c_imx-  pm_runtime_force_suspend);

 ret = pm_runtime_put_sync  _maybe_unused(struct *dev
 if (ret < 0)
  dev_err(&lpi2c_imx->adapter.dev, "failed ret;

 return ret;
}

static int /*
  struct platform_device *pdev)
{
struct i2c_bus_recovery_info *bri = &lpi2c_imx->rinfo;

bri->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(bri->pinctrl))
return PTR_ERR(bri->pinctrl);

lpi2c_imx->adapter.bus_recovery_info = bri;

return 0;
}

static void dma_exit(struct device *dev, struct lpi2c_imx_dma *dma)
{
if (dma->chan_rx)
dma_release_channel(dma->chan_rx);

if (dma->chan_tx)
dma_release_channel(dma->chan_tx);

devm_kfree(dev, dma);
}

static int lpi2c_dma_init(struct device *dev, dma_addr_t phy_addr)
{
struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
struct lpi2c_imx_dma *dma;
int ret;

dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
if (!dma)
return -ENOMEM;

dma->phy_addr = phy_addr;

/* Prepare for TX DMA: */

 dma->chan_tx = dma_request_chan(dev, "tx");
 if (IS_ERR  * the suspend_noirq() callback (pm_runtime_force_suspend()) is
  ret  * resume_noirq() callback (pm_runtime_force_resume()).
  if (ret != -ENODEV && ret !=  * the I2C controller remains available until the  * suspend_noirq() and from resume_noirq().
   }
  dma->chan_tx = NULL;
  goto
 }

 /* Prepare for RX DMA: */{
 dma->chan_rx = dma_request_chan(dev(devjava.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
 if (IS_ERR(dma->chan_rx)) {
  ret = PTR_ERR(dma->chan_rx const structdev_pm_opslpi2c_pm_ops ={
  if (ret        )
   (dev"'trequest DMA channel %d)n, ret)java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
  dma->chan_rx struct  ={
  goto dma_exit;
 }

 lpi2c_imx->can_use_dma = true;
 lpi2c_imx->dma = dma;
 return  . = ,

dma_exit:
 dma_exit(dev, dma); }
 return ret;
m(lpi2c_imx_driver

 u32i2c_adapter)
{
 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
  I2C_FUNC_SMBUS_READ_BLOCK_DATA;
}

static const struct i2c_algorithm lpi2c_imx_algo = {
 .xfer = lpi2c_imx_xfer,
 .xfer_atomic = lpi2c_imx_xfer_atomic,
 .functionality = lpi2c_imx_func,
 .reg_target = lpi2c_imx_register_target,
 .unreg_target = lpi2c_imx_unregister_target,
};

static const struct of_device_id lpi2c_imx_of_match[] = {
 { .compatible = "fsl,imx7ulp-lpi2c" },
 { }
};
MODULE_DEVICE_TABLE(of, lpi2c_imx_of_match);

static int lpi2c_imx_probe(struct platform_device *pdev)
{
 struct lpi2c_imx_struct *lpi2c_imx;
 struct resource *res;
 dma_addr_t phy_addr;
 unsigned int temp;
 int irq, ret;

 lpi2c_imx = devm_kzalloc(&pdev->dev, sizeof(*lpi2c_imx), GFP_KERNEL);
 if (!lpi2c_imx)
  return -ENOMEM;

 lpi2c_imx->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
 if (IS_ERR(lpi2c_imx->base))
  return PTR_ERR(lpi2c_imx->base);

 irq = platform_get_irq(pdev, 0);
 if (irq < 0)
  return irq;

 lpi2c_imx->adapter.owner = THIS_MODULE;
 lpi2c_imx->adapter.algo  = &lpi2c_imx_algo;
 lpi2c_imx->adapter.dev.parent = &pdev->dev;
 lpi2c_imx->adapter.dev.of_node = pdev->dev.of_node;
 strscpy(lpi2c_imx->adapter.name, pdev->name,
  sizeof(lpi2c_imx->adapter.name));
 phy_addr = (dma_addr_t)res->start;

 ret = devm_clk_bulk_get_all(&pdev->dev, &lpi2c_imx->clks);
 if (ret < 0)
  return dev_err_probe(&pdev->dev, ret, "can't get I2C peripheral clock\n");
 lpi2c_imx->num_clks = ret;

 ret = of_property_read_u32(pdev->dev.of_node,
       "clock-frequency", &lpi2c_imx->bitrate);
 if (ret)
  lpi2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ;

 ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, IRQF_NO_SUSPEND,
          pdev->name, lpi2c_imx);
 if (ret)
  return dev_err_probe(&pdev->dev, ret, "can't claim irq %d\n", irq);

 i2c_set_adapdata(&lpi2c_imx->adapter, lpi2c_imx);
 platform_set_drvdata(pdev, lpi2c_imx);

 ret = clk_bulk_prepare_enable(lpi2c_imx->num_clks, lpi2c_imx->clks);
 if (ret)
  return ret;

 /*
 * Lock the parent clock rate to avoid getting parent clock upon
 * each transfer
 */

 ret = devm_clk_rate_exclusive_get(&pdev->dev, lpi2c_imx->clks[0].clk);
 if (ret)
  return dev_err_probe(&pdev->dev, ret,
         "can't lock I2C peripheral clock rate\n");

 lpi2c_imx->rate_per = clk_get_rate(lpi2c_imx->clks[0].clk);
 if (!lpi2c_imx->rate_per)
  return dev_err_probe(&pdev->dev, -EINVAL,
         "can't get I2C peripheral clock rate\n");

 pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
 pm_runtime_use_autosuspend(&pdev->dev);
 pm_runtime_get_noresume(&pdev->dev);
 pm_runtime_set_active(&pdev->dev);
 pm_runtime_enable(&pdev->dev);

 temp = readl(lpi2c_imx->base + LPI2C_PARAM);
 lpi2c_imx->txfifosize = 1 << (temp & 0x0f);
 lpi2c_imx->rxfifosize = 1 << ((temp >> 8) & 0x0f);

 /* Init optional bus recovery function */
 ret = lpi2c_imx_init_recovery_info(lpi2c_imx, pdev);
 /* Give it another chance if pinctrl used is not ready yet */
 if (ret == -EPROBE_DEFER)
  goto rpm_disable;

 /* Init DMA */
 ret = lpi2c_dma_init(&pdev->dev, phy_addr);
 if (ret) {
  if (ret == -EPROBE_DEFER)
   goto rpm_disable;
  dev_info(&pdev->dev, "use pio mode\n");
 }

 ret = i2c_add_adapter(&lpi2c_imx->adapter);
 if (ret)
  goto rpm_disable;

 pm_runtime_mark_last_busy(&pdev->dev);
 pm_runtime_put_autosuspend(&pdev->dev);

 dev_info(&lpi2c_imx->adapter.dev, "LPI2C adapter registered\n");

 return 0;

rpm_disable:
 pm_runtime_dont_use_autosuspend(&pdev->dev);
 pm_runtime_put_sync(&pdev->dev);
 pm_runtime_disable(&pdev->dev);

 return ret;
}

static void lpi2c_imx_remove(struct platform_device *pdev)
{
 struct lpi2c_imx_struct *lpi2c_imx = platform_get_drvdata(pdev);

 i2c_del_adapter(&lpi2c_imx->adapter);

 pm_runtime_disable(&pdev->dev);
 pm_runtime_dont_use_autosuspend(&pdev->dev);
}

static int __maybe_unused lpi2c_runtime_suspend(struct device *dev)
{
 struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);

 clk_bulk_disable(lpi2c_imx->num_clks, lpi2c_imx->clks);
 pinctrl_pm_select_sleep_state(dev);

 return 0;
}

static int __maybe_unused lpi2c_runtime_resume(struct device *dev)
{
 struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
 int ret;

 pinctrl_pm_select_default_state(dev);
 ret = clk_bulk_enable(lpi2c_imx->num_clks, lpi2c_imx->clks);
 if (ret) {
  dev_err(dev, "failed to enable I2C clock, ret=%d\n", ret);
  return ret;
 }

 return 0;
}

static int __maybe_unused lpi2c_suspend_noirq(struct device *dev)
{
 return pm_runtime_force_suspend(dev);
}

static int __maybe_unused lpi2c_resume_noirq(struct device *dev)
{
 struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
 int ret;

 ret = pm_runtime_force_resume(dev);
 if (ret)
  return ret;

 /*
 * If the I2C module powers down during system suspend,
 * the register values will be lost. Therefore, reinitialize
 * the target when the system resumes.
 */

 if (lpi2c_imx->target)
  lpi2c_imx_target_init(lpi2c_imx);

 return 0;
}

static int lpi2c_suspend(struct device *dev)
{
 /*
 * Some I2C devices may need the I2C controller to remain active
 * during resume_noirq() or suspend_noirq(). If the controller is
 * autosuspended, there is no way to wake it up once runtime PM is
 * disabled (in suspend_late()).
 *
 * During system resume, the I2C controller will be available only
 * after runtime PM is re-enabled (in resume_early()). However, this
 * may be too late for some devices.
 *
 * Wake up the controller in the suspend() callback while runtime PM
 * is still enabled. The I2C controller will remain available until
 * the suspend_noirq() callback (pm_runtime_force_suspend()) is
 * called. During resume, the I2C controller can be restored by the
 * resume_noirq() callback (pm_runtime_force_resume()).
 *
 * Finally, the resume() callback re-enables autosuspend, ensuring
 * the I2C controller remains available until the system enters
 * suspend_noirq() and from resume_noirq().
 */

 return pm_runtime_resume_and_get(dev);
}

static int lpi2c_resume(struct device *dev)
{
 pm_runtime_mark_last_busy(dev);
 pm_runtime_put_autosuspend(dev);

 return 0;
}

static const struct dev_pm_ops lpi2c_pm_ops = {
 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(lpi2c_suspend_noirq,
          lpi2c_resume_noirq)
 SYSTEM_SLEEP_PM_OPS(lpi2c_suspend, lpi2c_resume)
 SET_RUNTIME_PM_OPS(lpi2c_runtime_suspend,
      lpi2c_runtime_resume, NULL)
};

static struct platform_driver lpi2c_imx_driver = {
 .probe = lpi2c_imx_probe,
 .remove = lpi2c_imx_remove,
 .driver = {
  .name = DRIVER_NAME,
  .of_match_table = lpi2c_imx_of_match,
  .pm = &lpi2c_pm_ops,
 },
};

module_platform_driver(lpi2c_imx_driver);

MODULE_AUTHOR("Gao Pan ");
MODULE_DESCRIPTION("I2C adapter driver for LPI2C bus");
MODULE_LICENSE("GPL");

Messung V0.5
C=94 H=93 G=93

¤ 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.15Bemerkung:  ¤

*Bot Zugriff






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.