\documentclass[aspectratio=43,obeyspaces,spaces,hyphens,dvipsnames]{beamer}
\usepackage[utf8x]{inputenc}
\usepackage{lmodern}% http://ctan.org/pkg/lm
\usepackage{minted}
\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{pgfplots}
\usepackage{tikz}
\usepackage[normalem]{ulem}
\usepackage{textcomp}
\usepackage{media9}

\mode<presentation>
\usetheme{Bootlin}

\def\signed #1{{\leavevmode\unskip\nobreak\hfil\penalty50\hskip2em
  \hbox{}\nobreak\hfil(#1)
  \parfillskip=0pt \finalhyphendemerits=0 \endgraf}}

\newsavebox\mybox
\newenvironment{aquote}[1]
  {\savebox\mybox{#1}\begin{quotation}}
  {\signed{\usebox\mybox}\end{quotation}}

\title{I3C in tomorrow's designs}
\conference{Embedded Linux Conference, Fall 2021}
\authors{Miquèl Raynal}
\email{\tiny miquel@bootlin.com}
\institute{Bootlin}
\slidesurl{https://bootlin.com/pub/conferences/2021/elc/raynal-i3c}

\begin{document}

\addtocontents{toc}{\protect\setcounter{tocdepth}{-1}}
\section{I3C in tomorrow's designs}
\addtocontents{toc}{\protect\setcounter{tocdepth}{2}}

\begin{frame}{Miquèl Raynal}
  \begin{itemize}
  \item Embedded Linux engineer at Bootlin
    \begin{itemize}
    \item Embedded Linux {\bf expertise}
    \item {\bf Development}, consulting and training
    \item Strong open-source focus
    \item \url{https://bootlin.com}
    \end{itemize}
  \item Contributions
    \begin{itemize}
    \item {\bf Maintainer of the NAND subsystem}
    \item {\bf Co-maintainer of the MTD subsystem}
    \item {\bf Kernel support for various ARM SoCs}
    \item {\bf Contributor to the I3C sybsystem}
    \end{itemize}
  \item Living in {\bf Toulouse}, south west of France
  \end{itemize}
\end{frame}

\section{Yet another serial bus?}

\begin{frame}{Electrical engineering 101}
  \center \Large
  You are a hardware designer.
  \vfill
  You want to wire a simple device to a custom board.
  \vfill
  What bus do you pick?
\end{frame}

\begin{frame}{Electrical engineering 101}
  \begin{itemize}
    \item Existing device interfaces?
    \item Power consumption targets?
    \item Expected throughput?
    \item Wiring constraints?
    \item Number of devices?
      \break
    \item Pick one:
      \begin{itemize}
      \item OneWire? Too simple/slow?
      \item RS232? Really?
      \item USB? Really suitable for embedded systems?
      \item I2C? Why not?
      \item SPI? Yeah, still trendy?
      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Electrical engineering 101}
  \center \Large
  You are a hardware designer.
  \vfill
  Now you want to wire several devices. \\
  You have minimal bandwidth constraints. \\
  The devices are a bit complex. \\
  \vfill
  What bus do you pick?
\end{frame}

\begin{frame}{State of the art}
  \begin{itemize}
  \item I2C is pretty slow (400kHz); SPI is fast (up to 100MHz)
    \begin {itemize}
    \item Slowest exchanges will last longer
    \item Longer exchanges will increase the power consumed per bit
      transmitted ratio
    \item Slow bus with many devices means extra delays
    \end{itemize}
    \break
  \item SPI needs one physical CS {\bf per device}; I2C doesn't, but
    suffers from address collision issues (lack of virtual addressing)
    \begin{itemize}
    \item Extra wires on a serial bus are costly
    \item I2C won't natively support more than a couple of identical
      devices
    \item In both cases, if asynchronous signaling is needed (IRQ), an
      additional line must be wired
    \end{itemize}
  \item Devices not available anymore on the bus after entering low
    power modes
  \item Devices don't natively belong to a particular ``class'' sharing
    a set of properties (easing the tuning of a set of devices)
  \end{itemize}
\end{frame}

\begin{frame}{Here comes I3C}
  \begin{itemize}
  \item {\bf Improved} Inter Integrated Circuit
  \item MIPI Alliance specification
  \item Targets automotive, consumer electronics, IoT market
  \item Two-wire bus with the following main features:
    \begin{itemize}
      \item Reasonably high throughput
      \item Colorful set of commands
      \item Dynamic address assignment
      \item Self-describing devices (USB-like)
      \item In-band signaling
      \item Hot-join
      \item Controller handover
      \item Advanced low-power modes
      \item And more...
    \end{itemize}
  \item Partially backward compatible with I2C
  \end{itemize}
\end{frame}

\begin{frame}{Backward compatibility with I2C}
  \begin{itemize}
  \item Main goal:
    \begin{itemize}
    \item Ease acceptance
    \item Improve the re-usability of existing devices
    \end{itemize}
  \item Designed with I2C in mind
    \begin{itemize}
    \item At physical level:
      \begin{itemize}
      \item Compatible Voltage levels
      \item A clock and a data line
      \item Adaptable clock frequencies
      \item Support for open-drain output
      \end{itemize}
    \item At logical level:
      \begin{itemize}
      \item 7-bits addressing
      \item Comparable
        \code{S}/\code{Sr}/\code{P}/\code{ACK}/\code{NACK} behavior
      \end{itemize}
    \item Use tricks to talk to I2C and I3C devices on the same bus
    \end{itemize}
  \end{itemize}
\end{frame}

\section{The I3C protocol}

\begin{frame}{Achieving higher frequencies}
  \begin{itemize}
  \item I2C relies on open-drain outputs with pull-ups
  \item I3C relies on push-pull mode
    \begin{itemize}
    \item SCL always in push-pull mode
    \item SDA alternating push-pull and open-drain
    \end{itemize}
  \end{itemize}
  \begin{center}
    % Taken from Boris Brezillon ELC 2018 I3C talk
    \includegraphics[height=0.5\textwidth]{open-drain-vs-push-pull.pdf}
  \end{center}
  $\Rightarrow$ faster rising times
\end{frame}

\begin{frame}{Pure I3C frequencies}
  I3C bus typical frequency is 12.5MHz. A ``Pure Bus'' supports:
  \begin{itemize}
  \item \code{SDR} (Simple Data Rate) mode achieves 12.5Mpbs
  \item \code{SDR} is the default mode and should be supported by all
    I3C devices
  \item Optional \code{HDR} (High Data Rate) modes
    \begin{itemize}
    \item Double Data Rate (\code{HDR-DDR}) achieves 25Mbps
      \begin{itemize}
      \item Still uses the clock
      \item Samples data on both edges of the clock
      \end{itemize}
    \item Ternary Symbol Pure (\code{HDR-TSP}) achieves 33.3Mbps
      \begin{itemize}
      \item Both signals are considered data
      \item Tracks edges rather than levels
      \item Each transition is a clock cycle, the bus is capable of
        expressing three states: \code{SCL} transitioned, \code{SDA}
        transitioned, \code{SCL} and \code{SDA} transitioned
      \end{itemize}
    \end{itemize}
  \end{itemize}
  \break
  \small The MIPI alliance states that higher frequencies only work well with
  point-to-point topologies:
  \scriptsize \url{https://www.mipi.org/resources/I3C-frequently-asked-questions}
\end{frame}

\begin{frame}{Pure I3C frequencies}
  \begin{itemize}
  \item The controller must advertise all targets that it is entering a
    \code{HDR} mode and which mode it has chosen
  \item If a device does not support the chosen \code{HDR} mode that the
    controller is entering, it can simply wait for the \code{HDR} mode to be
    exited
  \item All targets should support tracking the \code{HDR} exit pattern
    \begin{itemize}
    \item 4 \code{SDA} fall transitions with \code{SCL} low before a
      \code{P} pattern
    \item The \code{HDR} exit pattern detector is very cheap to
      implement (simply with 4 latches in series)
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Bandwidth: mixed modes}
  \begin{itemize}
  \item \code{SCL} being configured in push-pull, clock stretching is not
    allowed
  \item I2C devices must not be confused by the high-frequency exchanges
    \begin{itemize}
    \item Most I2C devices already have a 50ns anti-glitch spike filter
    \item I3C max bus frequency: 12.5MHz $\Rightarrow$ 80ns clock period
    \item When talking at 12.5MHz I2C devices won't even notice clock
      changes
    \item Asymmetrical clock: less than 50\% duty cycle in order to keep
      the low state longer than 50ns and be sure to be filtered out
      before reaching the I2C device
    \item A ``Mixed Fast Bus'' supports the following clock modes:
      \begin{itemize}
      \item \code{SDR}
      \item \code{HDR-DDR}
      \item Ternary Symbol Legacy (\code{HDR-TSL}) in place of
        \code{HDR-TSP}
      \end{itemize}
    \end{itemize}
  \item If an I2C device has no spike filter, it's considered a ``Mixed
    Slow/Limited bus'', the bus may only work at the slowest device speed
  \end{itemize}
\end{frame}

\begin{frame}{Enhanced bus management}
  \begin{itemize}
  \item Common Command Codes (\code{CCC})
  \item Standardization of the bus management
  \item Serve all kind of purpose
  \item Supports broadcast and direct addressing
  \item \code{CCC}s are always sent to the broadcast address
    \begin{itemize}
    \item 0x7E is the I3C broadcast address
    \item 0x7E is reserved in the I2C specification
    \item All I3C devices should listen at the entire command
    \end{itemize}
  \end{itemize}
  \begin{center}
    \includegraphics[width=1\textwidth]{ccc.pdf}
  \end{center}
\end{frame}

\begin{frame}{Common Command Codes (\code{CCC})}
  \begin{itemize}
  \item \code{ENTDAA}: Start a \code{DAA} procedure (auto-discovery
    procedure)
  \item \code{ENTASX}: Enter Activity State (related to power management)
  \item \code{GETPID}: Get Provisional ID (related to device
    identification)
  \item \code{GETBCR}: Get Bus Characteristics Register (related to
    device capabilities)
  \item \code{GETDCR}: Get Device Characteristics Register (related to
    device classification)
  \end{itemize}
  \code{ENEC}, \code{DISEC}, \code{ENTAS0}, \code{ENTAS1},
  \code{ENTAS2}, \code{ENTAS3}, \code{RSTDAA}, \code{ENTDAA},
  \code{DEFSLVS}, \code{SETMWL}, \code{SETMRL}, \code{ENTTM},
  \code{ENTHDR0}, \code{ENTHDR1}, \code{ENTHDR2}, \code{ENTHDR3},
  \code{ENTHDR7}, \code{SETXTIME}, \code{ENEC}, \code{DISEC},
  \code{ENTAS0}, \code{ENTAS1}, \code{ENTAS2}, \code{ENTAS3},
  \code{RSTDAA}, \code{SETDASA}, \code{SETNEWDA}, \code{SETMWL},
  \code{SETMRL}, \code{GETMWL}, \code{GETMRL}, \code{GETPID},
  \code{GETBCR}, \code{GETDCR}, \code{GETSTATUS}, \code{GETACCMST},
  \code{SETBRGTGT}, \code{GETMXDS}, \code{GETHDRCAP}, \code{SETXTIME},
  \code{GETXTIME}...
\end{frame}

\begin{frame}{Dynamic Address Assignment (\code{DAA})}
  \begin{itemize}
  \item Regular exchanges on the I3C bus require a dynamic 7-bit address
  \item I2C devices already have one and the controller knows about them
    \begin{itemize}
    \item Must be statically described, like any regular I2C device
    \end{itemize}
  \item I3C devices must get part of the \code{DAA} procedure in order to
    receive a 7-bit dynamic identifier
    \begin{itemize}
    \item Unless they have a static address as well and the controller knows
      about it
    \item Or they are in a deep sleep state/powered down at that moment
      \begin{itemize}
        \item They will require the \code{DAA} procedure to be resumed
          when they will become available
      \end{itemize}
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Device unique identification}
  \begin{itemize}
  \item Each device has its own unique Provisional ID (\code{PID})
    48-bit identifier:
    \begin{itemize}
    \item 15 bits for the MIPI manufacturer ID
    \item 1 bit indicating if the below values are random or not
    \item 32 bits for the Part ID, Instance ID and more bits left to the
      vendor to define
    \end{itemize}
  \item Device also advertise a Bus Characteristics Register \code{BCR}
    which contains:
    \begin{itemize}
    \item The device role (controller/target)
    \item Its potential \code{SDR} limitations
    \item Its \code{HDR} capabilities
    \item Its offline capabilities
    \item Its in-band signaling capabilities
    \end{itemize}
  \item It also has a Device Characteristics Register \code{DCR}
    which describes the type of device (accelerometer, thermometer,
    composite, etc)
    \begin{itemize}
    \item This calls for standardized interfaces!
    \end{itemize}
  \item \code{PID}, \code{BCR} and \code{DCR} will be advertised during
    the \code{DAA} procedure
  \end{itemize}
\end{frame}

\begin{frame}{\code{DAA}}
  The controller sends \code{ENTDAA}, generates a \code{Sr} and sends
  the broadcast address (0x7E).
  \begin{center}
    \includegraphics[height=0.5\textwidth]{daa-entdaa.pdf}
  \end{center}
\end{frame}

\begin{frame}{\code{DAA}}
  All I3C devices are expected to \code{ACK}.
  \begin{center}
    \includegraphics[height=0.5\textwidth]{daa-first-acks.pdf}
  \end{center}
\end{frame}

\begin{frame}{\code{DAA}}
  All I3C devices send their \code{PID}.
  \begin{center}
    \includegraphics[height=0.5\textwidth]{daa-first-pids.pdf}
  \end{center}
\end{frame}

\begin{frame}{\code{DAA}}
  The target with the highest \code{PID} looses the arbitration (thanks
  to the open-drain nature of the \code{SDA} line during this exchange).
  \begin{center}
    \includegraphics[height=0.5\textwidth]{daa-first-pids-arbitration.pdf}
  \end{center}
  The winning device sends its \code{PID} followed by its \code {BCR}
  and \code{DCR}.
\end{frame}

\begin{frame}{\code{DAA}}
  The controller sends a 7-bit address to the winning device that will
  become its own dynamic address.
  \begin{center}
    \includegraphics[height=0.5\textwidth]{daa-dynaddr-sent.pdf}
  \end{center}
\end{frame}

\begin{frame}{\code{DAA}}
  The target will acknowledge this dynamic address.
  \begin{center}
    \includegraphics[height=0.5\textwidth]{daa-dynaddr-acked.pdf}
  \end{center}
\end{frame}

\begin{frame}{\code{DAA}}
  The controller generates a (\code{Sr}) condition and sends the
  broadcast address again.
  \begin{center}
    \includegraphics[height=0.5\textwidth]{daa-second-restart.pdf}
  \end{center}
\end{frame}

\begin{frame}{\code{DAA}}
  All devices that have not yet received a dynamic address should
  \code{ACK} it again.
  \begin{center}
    \includegraphics[height=0.5\textwidth]{daa-second-restart-ack.pdf}
  \end{center}
\end{frame}

\begin{frame}{\code{DAA}}
  The new winning device sends its identification numbers.
  \begin{center}
    \includegraphics[height=0.5\textwidth]{daa-second-pid.pdf}
  \end{center}
\end{frame}

\begin{frame}{\code{DAA}}
  The controller provides to the device a different dynamic address.
  \begin{center}
    \includegraphics[height=0.5\textwidth]{daa-second-dynaddr-sent.pdf}
  \end{center}
\end{frame}

\begin{frame}{\code{DAA}}
  The target device again acknowledges its new dynamic address.
  \begin{center}
    \includegraphics[height=0.5\textwidth]{daa-second-dynaddr-ack.pdf}
  \end{center}
\end{frame}

\begin{frame}{\code{DAA}}
  The controller keeps repeating the procedure...
  \begin{center}
    \includegraphics[height=0.5\textwidth]{daa-third-restart.pdf}
  \end{center}
\end{frame}

\begin{frame}{\code{DAA}}
  ...until there are no more devices acknowledging the request anymore,
  this means all woken-up devices have their dynamic address and the bus
  is now operational.
  \begin{center}
    \includegraphics[height=0.5\textwidth]{daa-nack.pdf}
  \end{center}
\end{frame}

\begin{frame}{\code{IBI}s}
  \begin{itemize}
  \item Device driven In-Band Interrupts
  \item The device can raise an interrupt in the following conditions:
    \begin{itemize}
    \item The controller initiate a start condition: \code{SDA} low then
      \code{SCL} low
    \item The bus is idle, the device asserts \code{SDA} low and waits for
      the controller to acknowledge the interrupt by pulling \code{SCL} low to
      end the start condition
    \end{itemize}
  \item Device sends its address with a RnW bit to 1
  \item Priority arbitration depends on the dynamic address
    \begin{itemize}
    \item Address exchange in open drain mode
      \begin{itemize}
      \item 0 has a higher ``priority'' than 1
      \item Lowest address $\Rightarrow$ highest priority
      \end{itemize}
    \end{itemize}
  \item Controller \code{ACK}s or \code{NACK}s the interrupt
  \item Some devices may also provide a mandatory byte that the controller
    must read
  \item The controller decides to emit a \code{Sr} and continue talking
    on the bus or emits a \code{P}
  \end{itemize}
\end{frame}

\begin{frame}{Hot-join}
  \begin{itemize}
  \item Devices can be unpowered and powered back at any moment, thus
    improving the energy savings
  \item Physically plugged-in devices at run-time
  \item A hot-join request is very much like an \code{IBI} but the
    device will provide a reserved address followed by a specific RnW
    bit to 0 in order to request a new \code{DAA} round
  \end{itemize}
\end{frame}

\begin{frame}{Controller handover}
  \begin{itemize}
  \item Controller handover works very similarly than a hot-join, the
    device sending its own address this time, and keeping the RnW bit
    set to 0
  \item If the current controller does not feel ready, it may
    \code{NACK} the request
    \begin{itemize}
      \item The offended target may request to be granted primary
        controller later
    \end{itemize}
  \item If the controller agrees, it needs to prepare the bus for hand-off
    \begin{itemize}
    \item Disable specific requests, wait for targets to finish their
      current processing, disable interrupts, ...
    \item Assert a particular \code{CCC} to proceed the hand-off and end
      the transaction with a \code{P}
    \item Arbitration has been lost, the controller should release the
      lines and check that the new controller now asserts its
      controllership
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Time synchronization (I3C v1.1)}
  \begin{itemize}
  \item A device might receive the order from the controller to generate
    samples at a given rate instead of on-demand only
  \item Controller would issue a \code{SETXTIME} to setup the frequency
  \item The target is then suppose to generate an \code{IBI} each time it
    triggers a sample
    \break
  \item Also a way of synchronizing different devices if an external low
    power clock is shared among several devices in order to trigger the
    sampling
  \end{itemize}
\end{frame}

\begin{frame}{Reset (I3C v1.1)}
  \begin{itemize}
  \item Global reset:
    \begin{itemize}
    \item Upon error showing that the bus is currently stuck, the I3C
      controller is capable of sending a global reset over the bus
    \item Only supposed to reset the bus controller of each device
    \item Implies restarting the DAA procedure
    \end{itemize}
    \vfill
  \item Targeted reset:
    \begin{itemize}
    \item A target might request to be reset
    \item Saves an extra line on the final design
    \item Involves asking all the devices but the one requesting the
      reset to discard the comming ``reset pattern''
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Reset (I3C v1.1)}
  \begin{itemize}
  \item \code{RSTACT} specifies how the targets should react to a
    ``reset pattern'':
    \begin{itemize}
    \item Discard
    \item Reset the bus controller
    \item Reset the entire chip
    \end{itemize}
    \item A reset pattern is made of 14 \code{SDA} transitions with
      \code{SCL} kept low, a \code{Sr} and finally a \code{P}
  \end{itemize}
\end{frame}

\begin{frame}{Bulk Transport (I3C v1.1)}
  \begin{itemize}
  \item New Bulk Transport (\code{HDR-BT}) mode for Bulk messages
    \begin{itemize}
    \item Typical use: direct mapping of a SRAM
    \end{itemize}
  \item Enhanced CRC checks with the sender knowing rapidly if the
    transfer must be repeated
  \item Lowered overhead
  \item The target can drive \code{SCL} during reads to avoid
    round-trip-time issues during long transfers
  \end{itemize}
\end{frame}

\begin{frame}{Multi-Lane (I3C v1.1)}
  \begin{itemize}
  \item After so much efforts to keep everything in-band as much as
    possible, it was time to add new wires...
    \begin{itemize}
    \item \code{SDR-ML DUAL}
    \item \code{SDR-ML QUAD}
    \item \code{HDR-DDR-ML DUAL}
    \item \code{HDR-DDR-ML QUAD}
    \item \code{HDR-TSP-ML DUAL}
    \item \code{HDR-TSP-ML QUAD}
    \item \code{HDR-BT-ML DUAL}
    \item \code{HDR-BT-ML QUAD}
    \end{itemize}
  \end{itemize}
\end{frame}

\section{Linux API}

\begin{frame}{The I3C framework}
  \begin{center}
    % Taken from Boris Brezillon ELC 2018 I3C talk
    \includegraphics[width=0.9\textwidth]{i3c-framework.pdf}
  \end{center}
\end{frame}

\begin{frame}[fragile]{Design choices}
  \begin{itemize}
  \item Built as a separate subsystem than I2C in order not to break the
    I2C framework
  \item The subsystem defines:
    \begin{itemize}
    \item A \code{struct i3c_bus} bus object
    \item A \code{struct i3c_master_controller} controller structure
    \item A rather exhaustive \code{struct i3c_master_controller_ops}
      interface
    \item All the necessary APIs to register:
      \begin{itemize}
      \item A controller
      \item A device driver
      \item \code{IBI}s
      \end{itemize}
    \end{itemize}
  \item Device-driver binding are based on the device's \code{PID}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{The I3C bus infrastructure}
  \begin{block}{include/linux/i3c/master.h}
    \begin{minted}[fontsize=\scriptsize]{c}
struct i3c_bus {
	struct i3c_dev_desc *cur_master;
	int id;
	unsigned long addrslots[((I2C_MAX_ADDR+1) * 2) / BITS_PER_LONG];
	enum i3c_bus_mode mode;
	struct {
		unsigned long i3c;
		unsigned long i2c;
	} scl_rate;
	struct {
		struct list_head i3c;
		struct list_head i2c;
	} devs;
	struct rw_semaphore lock;
};
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}[fragile]{The I3C controller structure}
  \begin{block}{include/linux/i3c/master.h}
    \begin{minted}[fontsize=\scriptsize]{c}
struct i3c_master_controller {
	struct device dev;
	struct i3c_dev_desc *this;
	struct i2c_adapter i2c;
	const struct i3c_master_controller_ops *ops;
	unsigned int secondary : 1;
	unsigned int init_done : 1;
	struct {
		struct list_head i3c;
		struct list_head i2c;
	} boardinfo;
	struct i3c_bus bus;
	struct workqueue_struct *wq;
};
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}[fragile]{The I3C controller interface}
  \begin{block}{include/linux/i3c/master.h}
    \begin{minted}[fontsize=\tiny]{c}
struct i3c_master_controller_ops {
	/* Bus management */
	int (*bus_init)(struct i3c_master_controller *master);
	void (*bus_cleanup)(struct i3c_master_controller *master);
	int (*do_daa)(struct i3c_master_controller *master);
        /* I3C devices management */
	int (*attach_i3c_dev)(struct i3c_dev_desc *dev);
	int (*reattach_i3c_dev)(struct i3c_dev_desc *dev, u8 old_dyn_addr);
	void (*detach_i3c_dev)(struct i3c_dev_desc *dev);
        /* CCCs transactions */
	bool (*supports_ccc_cmd)(struct i3c_master_controller *master,
				 const struct i3c_ccc_cmd *cmd);
	int (*send_ccc_cmd)(struct i3c_master_controller *master, struct i3c_ccc_cmd *cmd);
	/* Private SDR transfers */
	int (*priv_xfers)(struct i3c_dev_desc *dev, struct i3c_priv_xfer *xfers, int nxfers);
	/* I2C devices management */
	int (*attach_i2c_dev)(struct i2c_dev_desc *dev);
	void (*detach_i2c_dev)(struct i2c_dev_desc *dev);
	int (*i2c_xfers)(struct i2c_dev_desc *dev, const struct i2c_msg *xfers, int nxfers);
	/* IBI management */
	int (*request_ibi)(struct i3c_dev_desc *dev, const struct i3c_ibi_setup *req);
	void (*free_ibi)(struct i3c_dev_desc *dev);
	int (*enable_ibi)(struct i3c_dev_desc *dev);
	int (*disable_ibi)(struct i3c_dev_desc *dev);
	void (*recycle_ibi_slot)(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot);
};
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}{Additional information about bus initialization}
  \begin{itemize}
  \item The core parses the information provided by the DT
  \item Static devices are instantiated on this base
  \item Calls the \code{->bus_init()} callback to initialize the
    controller
  \item Calls the \code{->do_daa()} callback to start the device
    discovery
    \begin{itemize}
    \item Assigns dynamic addresses \code{DAA}
    \item The way the controller wants to follow the \code{DAA}
      procedure is really open
    \item For each device discovered, the controller driver calls
      \code{i3c_master_add_i3c_dev_locked()} to notify the core
    \end{itemize}
  \item The core then registers the discovered devices to the device
    model
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{The device interface}
  \begin{block}{include/linux/i3c/device.h}
    \begin{minted}[fontsize=\scriptsize]{c}
struct i3c_device {
        // Generic 'device-model' device structure
	struct device dev;
        // Internal representation of an I3C device
	struct i3c_dev_desc *desc;
        // Representation of the I3C bus, not tight to a specific
        // controller due to controller handover possibilities
	struct i3c_bus *bus;
};
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}[fragile]{An I3C device driver}
  \begin{block}{Dummy I3C device driver}
    \begin{minted}[fontsize=\tiny]{c}
static int dummy_i3c_probe(struct i3c_device *i3cdev)
{
	...
	i3cdev_set_drvdata(i3cdev, data);
}

static int dummy_i3c_remove(struct i3c_device *i3cdev)
{
	void *data = i3cdev_get_drvdata(i3cdev);
	...
}

static const struct i3c_device_id dummy_i3cdev_ids[] = {
	I3C_DEVICE(<manufid>, <partid>, <driver-data>),
	{ /* sentinel */ },
};

static struct i3c_driver dummy_i3c_drv = {
        .driver = {
                .name = "dummy-i3c",
	},
	.id_table = dummy_i3cdev_ids,
	.probe = dummy_i3c_probe,
	.remove = dummy_i3c_remove,
};
module_i3c_driver(dummy_i3c_drv);
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Interacting with the I3C device}
  \begin{block}{SDR transfers}
    \begin{minted}[fontsize=\scriptsize]{c}
u8 reg = 0x5, values[2];
struct i3c_priv_xfer xfers[2] = {
	{
		.flags = 0,
		.len = 1,
		.data.out = &reg,
	},
	{
		.flags = I3C_PRIV_XFER_READ,
		.len = 2,
		.data.in = values,
	},
};

ret = i3c_device_do_priv_xfers(i3cdev, xfers, ARRAY_SIZE(xfers));
if (ret)
	return ret;
    \end{minted}
  \end{block}
  $\Rightarrow$ \code{CCC}s for now are not exposed (subject to
  evolution)
\end{frame}

\begin{frame}[fragile]{Using \code{IBI}s}
  \begin{block}{}
    \begin{minted}[fontsize=\tiny]{c}
/* Called in a non-atomic context (workqueue) */
static void ibi_handler(struct i3c_device *i3cdev,
                        const struct i3c_ibi_payload *payload);

static int probe(struct i3c_device *i3cdev)
{
	struct i3c_ibi_setup ibireq = {
		.handler = ibi_handler,
		.max_payload_len = 2,
		.num_slots = 10,
	};

	...
	ret = i3c_device_request_ibi(dev, &ibireq);
	if (ret)
		return ret;

	ret = i3c_device_enable_ibi(dev);
	if (ret)
		return ret;
	...
}

static int remove(struct i3c_device *i3cdev)
{
	i3c_device_disable_ibi(i3cdev);
	i3c_device_free_ibi(i3cdev);
	...
}
    \end{minted}
  \end{block}
  \small $\Rightarrow$ Slots are pre-allocated, possible overlap if not
  unqueued fast enough
\end{frame}

\begin{frame}{Status and to-do list}
  \begin{itemize}
  \item Things have moved forward
    \begin{itemize}
    \item Hardware manufacturers more and more interested
    \item Three controller drivers upstream
    \item One IMU device driver upstream (not fully leveraging the power
      of I3C yet)
    \item Ongoing controller handover work \\
      \url{https://lkml.kernel.org/lkml/1606716983-3645-1-git-send-email-pthombar@cadence.com/}
    \end{itemize}
    \vfill
  \item There is still room for improvement
    \begin{itemize}
    \item \code{HDR} support
    \item I3C target interface
    \item Global and directed resets
    \item Time synchronization
    \item \code{/dev} interface with additional user controls?
    \item ...
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Thanks!}
  \centering
  \Huge
  Questions? Suggestions? Comments?\\
  \vspace{0.5cm}
  \huge
  Miquèl Raynal\\
  \large
  \vspace{0.5cm}
  \hspace{1.85cm}\code{miquel@bootlin.com}
  \vspace{0.5cm}
  \newline Slides under CC-BY-SA 3.0\\
  \scriptsize
  \url{https://bootlin.com/pub/conferences/2021/i3c/raynal-i3c}
\end{frame}

\end{document}
