The Shiny New I2C Slave Framework Wolfram Sang Consultant/Renesas - - PowerPoint PPT Presentation

the shiny new i2c slave framework
SMART_READER_LITE
LIVE PREVIEW

The Shiny New I2C Slave Framework Wolfram Sang Consultant/Renesas - - PowerPoint PPT Presentation

The Shiny New I2C Slave Framework Wolfram Sang Consultant/Renesas Kernel Team 6.10.2015, ELCE15 Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 1 / 26 A typical I2C bus 1 6.10.2015, ELCE15 The Shiny


slide-1
SLIDE 1

The Shiny New I2C Slave Framework

Wolfram Sang

Consultant/Renesas Kernel Team

6.10.2015, ELCE15

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 1 / 26

slide-2
SLIDE 2

A typical I2C bus

Vdd SDA SCL Rp

Linux Master μC Slave Slave ADC Slave DAC

1

1picture based on this one by Colin M.L. Burnett

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 2 / 26

slide-3
SLIDE 3

The new era :)

Vdd SDA SCL Rp

Linux Ma./Sl. Linux Ma./Sl. Slave ADC Slave DAC

2

2picture based on this one by Colin M.L. Burnett

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 3 / 26

slide-4
SLIDE 4

Finally…

At this time, Linux only operates I2C (or SMBus) in master mode; you can’t use these APIs to make a Linux system behave as a slave/device, either to speak a custom protocol or to emulate some other device.

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 4 / 26

slide-5
SLIDE 5

Use cases

data delivery (sensor like) confjguration (codec like) embedded controllers (e.g. nvec) avoid multi-master

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 5 / 26

slide-6
SLIDE 6

Data fmow

User Backend Driver Controller kernel driver, sysfs, char device,... I2C slave events IO registers

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 6 / 26

slide-7
SLIDE 7

Driver side

We need support from the I2C bus driver

activating slave support in the core is not enough usually extension to the I2C master driver

no slave only solutions please

watch your PM settings

a slave always needs to listen

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 7 / 26

slide-8
SLIDE 8

Registering a slave

static int rcar_reg_slave(struct i2c_client *slave) { struct rcar_i2c_priv *priv = i2c_get_adapdata(slave->adapter); if (priv->slave) return -EBUSY; if (slave->flags & I2C_CLIENT_TEN) return -EAFNOSUPPORT; pm_runtime_forbid(rcar_i2c_priv_to_dev(priv)); priv->slave = slave; rcar_i2c_write(priv, ICSAR, slave->addr); rcar_i2c_write(priv, ICSSR, 0); rcar_i2c_write(priv, ICSIER, SAR | SSR); rcar_i2c_write(priv, ICSCR, SIE | SDBS); return 0; }

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 8 / 26

slide-9
SLIDE 9

Slave events

Handler function

ret = i2c_slave_event(slave, event, &val) links driver and backend val carries the data. It is bidirectional. usually called from interrupt context!

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 9 / 26

slide-10
SLIDE 10

Slave events (master writes)

S Addr+W Data A/N A ... P

I2C_SLAVE_WRITE_REQUESTED I2C_SLAVE_STOP I2C_SLAVE_WRITE_RECEIVED

val = byte from master, ret = 0/-ERRNO val = unused, ret = 0 val = unused, ret = 0

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 10 / 26

slide-11
SLIDE 11

Slave events (master reads)

S Addr+R Data A/N A ... P

I2C_SLAVE_READ_REQUESTED I2C_SLAVE_STOP I2C_SLAVE_READ_PROCESSED

val = byte to master, ret = 0 val = byte to master, ret = 0 val = unused, ret = 0

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 11 / 26

slide-12
SLIDE 12

Slave interrupt handler I

static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv) { u32 ssr_raw, ssr_filtered; u8 value; ssr_raw = rcar_i2c_read(priv, ICSSR) & 0xff; ssr_filtered = ssr_raw & rcar_i2c_read(priv, ICSIER); if (!ssr_filtered) return false;

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 12 / 26

slide-13
SLIDE 13

Slave interrupt handler II

/* address detected */ if (ssr_filtered & SAR) { /* read or write request */ if (ssr_raw & STM) { i2c_slave_event(priv->slave, I2C_SLAVE_READ_REQUESTED, &value); rcar_i2c_write(priv, ICRXTX, value); rcar_i2c_write(priv, ICSIER, SDE | SSR | SAR); } else { i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED, &value); rcar_i2c_read(priv, ICRXTX); /* dummy read */ rcar_i2c_write(priv, ICSIER, SDR | SSR | SAR); } rcar_i2c_write(priv, ICSSR, ~SAR & 0xff); }

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 13 / 26

slide-14
SLIDE 14

Slave interrupt handler III

/* master sent stop */ if (ssr_filtered & SSR) { i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value); rcar_i2c_write(priv, ICSIER, SAR | SSR); rcar_i2c_write(priv, ICSSR, ~SSR & 0xff); }

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 14 / 26

slide-15
SLIDE 15

Slave interrupt handler IV

/* master wants to write to us */ if (ssr_filtered & SDR) { int ret; value = rcar_i2c_read(priv, ICRXTX); ret = i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_RECEIVED, &value); /* Send NACK in case of error */ rcar_i2c_write(priv, ICSCR, SIE | SDBS | (ret < 0 ? FNA : 0)); rcar_i2c_write(priv, ICSSR, ~SDR & 0xff); }

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 15 / 26

slide-16
SLIDE 16

Slave interrupt handler V

/* master wants to read from us */ if (ssr_filtered & SDE) { i2c_slave_event(priv->slave, I2C_SLAVE_READ_PROCESSED, &value); rcar_i2c_write(priv, ICRXTX, value); rcar_i2c_write(priv, ICSSR, ~SDE & 0xff); } return true; }

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 16 / 26

slide-17
SLIDE 17

Backends

are standard i2c drivers are normally matched to i2c clients are HW independent provide a callback to handle slave events

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 17 / 26

slide-18
SLIDE 18

Backend driver I

static int i2c_slave_8bit_seconds_slave_cb(struct i2c_client *client, enum i2c_slave_event event, u8 *val) { switch (event) { case I2C_SLAVE_READ_REQUESTED: case I2C_SLAVE_READ_PROCESSED: /* Always get the most recent value */ *val = get_seconds() & 0xff; break; case I2C_SLAVE_WRITE_REQUESTED: case I2C_SLAVE_WRITE_RECEIVED: case I2C_SLAVE_STOP: default: break; } return 0; }

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 18 / 26

slide-19
SLIDE 19

Backend driver II

static int i2c_slave_8bit_seconds_probe(struct i2c_client *client, const struct i2c_device_id *id) { return i2c_slave_register(client, i2c_slave_8bit_seconds_slave_cb); }; static int i2c_slave_8bit_seconds_remove(struct i2c_client *client) { i2c_slave_unregister(client); return 0; }

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 19 / 26

slide-20
SLIDE 20

The ”read pointer” problem

... case I2C_SLAVE_READ_PROCESSED: /* The previous byte made it to the bus, get next one */ eeprom->buffer_idx++; /* fallthrough */ case I2C_SLAVE_READ_REQUESTED: spin_lock(&eeprom->buffer_lock); *val = eeprom->buffer[eeprom->buffer_idx]; spin_unlock(&eeprom->buffer_lock); /* * Do not increment buffer_idx here, because we don't know if * this byte will be actually used. Read Linux I2C slave docs * for details. */ break; ...

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 20 / 26

slide-21
SLIDE 21

Current status

Drivers: RCar, (Tegra), ((Davinci)) Backend: EEPROM/memory simulator Devicetree: bindings clear \o/

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 21 / 26

slide-22
SLIDE 22

Address spaces

Avoid address collisions. Enable loopbacks.

Devicetree

I2C_TEN_BIT_ADDRESS

address space: 0xa000 - 0xa3ff

I2C_OWN_SLAVE_ADDRESS

address space += 0x1000

Example:

reg = <(I2C_OWN_SLAVE_ADDRESS | 0x42)>;

Run time instantiation

echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-1/new_device

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 22 / 26

slide-23
SLIDE 23

Next steps

more driver support more backends (if there is a user) no new features (unless there is a use case)

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 23 / 26

slide-24
SLIDE 24

Thanks! <3

Renesas

for funding this upstream solution

Renesas Kernel Team

especially Geert and Laurent for thorough review

Uwe Kleine-König

for in-depth discussions

Andrey Danin

for the Tegra slave implementation and nvec backend port

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 24 / 26

slide-25
SLIDE 25

Demo!

At the showcase this evening

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 25 / 26

slide-26
SLIDE 26

The End

Thank you for your attention!

Questions? Comments?

right now at the showcase this evening

  • r anytime at this conference

wsa@the-dreams.de

Wolfram Sang (wsa@the-dreams.de) The Shiny New I2C Slave Framework 6.10.2015, ELCE15 26 / 26