162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2013 STMicroelectronics 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * I2C master mode controller driver, used in STMicroelectronics devices. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Maxime Coquelin <maxime.coquelin@st.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/clk.h> 1162306a36Sopenharmony_ci#include <linux/delay.h> 1262306a36Sopenharmony_ci#include <linux/err.h> 1362306a36Sopenharmony_ci#include <linux/i2c.h> 1462306a36Sopenharmony_ci#include <linux/interrupt.h> 1562306a36Sopenharmony_ci#include <linux/io.h> 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci#include <linux/of_address.h> 1862306a36Sopenharmony_ci#include <linux/of_irq.h> 1962306a36Sopenharmony_ci#include <linux/of.h> 2062306a36Sopenharmony_ci#include <linux/pinctrl/consumer.h> 2162306a36Sopenharmony_ci#include <linux/platform_device.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* SSC registers */ 2462306a36Sopenharmony_ci#define SSC_BRG 0x000 2562306a36Sopenharmony_ci#define SSC_TBUF 0x004 2662306a36Sopenharmony_ci#define SSC_RBUF 0x008 2762306a36Sopenharmony_ci#define SSC_CTL 0x00C 2862306a36Sopenharmony_ci#define SSC_IEN 0x010 2962306a36Sopenharmony_ci#define SSC_STA 0x014 3062306a36Sopenharmony_ci#define SSC_I2C 0x018 3162306a36Sopenharmony_ci#define SSC_SLAD 0x01C 3262306a36Sopenharmony_ci#define SSC_REP_START_HOLD 0x020 3362306a36Sopenharmony_ci#define SSC_START_HOLD 0x024 3462306a36Sopenharmony_ci#define SSC_REP_START_SETUP 0x028 3562306a36Sopenharmony_ci#define SSC_DATA_SETUP 0x02C 3662306a36Sopenharmony_ci#define SSC_STOP_SETUP 0x030 3762306a36Sopenharmony_ci#define SSC_BUS_FREE 0x034 3862306a36Sopenharmony_ci#define SSC_TX_FSTAT 0x038 3962306a36Sopenharmony_ci#define SSC_RX_FSTAT 0x03C 4062306a36Sopenharmony_ci#define SSC_PRE_SCALER_BRG 0x040 4162306a36Sopenharmony_ci#define SSC_CLR 0x080 4262306a36Sopenharmony_ci#define SSC_NOISE_SUPP_WIDTH 0x100 4362306a36Sopenharmony_ci#define SSC_PRSCALER 0x104 4462306a36Sopenharmony_ci#define SSC_NOISE_SUPP_WIDTH_DATAOUT 0x108 4562306a36Sopenharmony_ci#define SSC_PRSCALER_DATAOUT 0x10c 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* SSC Control */ 4862306a36Sopenharmony_ci#define SSC_CTL_DATA_WIDTH_9 0x8 4962306a36Sopenharmony_ci#define SSC_CTL_DATA_WIDTH_MSK 0xf 5062306a36Sopenharmony_ci#define SSC_CTL_BM 0xf 5162306a36Sopenharmony_ci#define SSC_CTL_HB BIT(4) 5262306a36Sopenharmony_ci#define SSC_CTL_PH BIT(5) 5362306a36Sopenharmony_ci#define SSC_CTL_PO BIT(6) 5462306a36Sopenharmony_ci#define SSC_CTL_SR BIT(7) 5562306a36Sopenharmony_ci#define SSC_CTL_MS BIT(8) 5662306a36Sopenharmony_ci#define SSC_CTL_EN BIT(9) 5762306a36Sopenharmony_ci#define SSC_CTL_LPB BIT(10) 5862306a36Sopenharmony_ci#define SSC_CTL_EN_TX_FIFO BIT(11) 5962306a36Sopenharmony_ci#define SSC_CTL_EN_RX_FIFO BIT(12) 6062306a36Sopenharmony_ci#define SSC_CTL_EN_CLST_RX BIT(13) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* SSC Interrupt Enable */ 6362306a36Sopenharmony_ci#define SSC_IEN_RIEN BIT(0) 6462306a36Sopenharmony_ci#define SSC_IEN_TIEN BIT(1) 6562306a36Sopenharmony_ci#define SSC_IEN_TEEN BIT(2) 6662306a36Sopenharmony_ci#define SSC_IEN_REEN BIT(3) 6762306a36Sopenharmony_ci#define SSC_IEN_PEEN BIT(4) 6862306a36Sopenharmony_ci#define SSC_IEN_AASEN BIT(6) 6962306a36Sopenharmony_ci#define SSC_IEN_STOPEN BIT(7) 7062306a36Sopenharmony_ci#define SSC_IEN_ARBLEN BIT(8) 7162306a36Sopenharmony_ci#define SSC_IEN_NACKEN BIT(10) 7262306a36Sopenharmony_ci#define SSC_IEN_REPSTRTEN BIT(11) 7362306a36Sopenharmony_ci#define SSC_IEN_TX_FIFO_HALF BIT(12) 7462306a36Sopenharmony_ci#define SSC_IEN_RX_FIFO_HALF_FULL BIT(14) 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/* SSC Status */ 7762306a36Sopenharmony_ci#define SSC_STA_RIR BIT(0) 7862306a36Sopenharmony_ci#define SSC_STA_TIR BIT(1) 7962306a36Sopenharmony_ci#define SSC_STA_TE BIT(2) 8062306a36Sopenharmony_ci#define SSC_STA_RE BIT(3) 8162306a36Sopenharmony_ci#define SSC_STA_PE BIT(4) 8262306a36Sopenharmony_ci#define SSC_STA_CLST BIT(5) 8362306a36Sopenharmony_ci#define SSC_STA_AAS BIT(6) 8462306a36Sopenharmony_ci#define SSC_STA_STOP BIT(7) 8562306a36Sopenharmony_ci#define SSC_STA_ARBL BIT(8) 8662306a36Sopenharmony_ci#define SSC_STA_BUSY BIT(9) 8762306a36Sopenharmony_ci#define SSC_STA_NACK BIT(10) 8862306a36Sopenharmony_ci#define SSC_STA_REPSTRT BIT(11) 8962306a36Sopenharmony_ci#define SSC_STA_TX_FIFO_HALF BIT(12) 9062306a36Sopenharmony_ci#define SSC_STA_TX_FIFO_FULL BIT(13) 9162306a36Sopenharmony_ci#define SSC_STA_RX_FIFO_HALF BIT(14) 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* SSC I2C Control */ 9462306a36Sopenharmony_ci#define SSC_I2C_I2CM BIT(0) 9562306a36Sopenharmony_ci#define SSC_I2C_STRTG BIT(1) 9662306a36Sopenharmony_ci#define SSC_I2C_STOPG BIT(2) 9762306a36Sopenharmony_ci#define SSC_I2C_ACKG BIT(3) 9862306a36Sopenharmony_ci#define SSC_I2C_AD10 BIT(4) 9962306a36Sopenharmony_ci#define SSC_I2C_TXENB BIT(5) 10062306a36Sopenharmony_ci#define SSC_I2C_REPSTRTG BIT(11) 10162306a36Sopenharmony_ci#define SSC_I2C_SLAVE_DISABLE BIT(12) 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci/* SSC Tx FIFO Status */ 10462306a36Sopenharmony_ci#define SSC_TX_FSTAT_STATUS 0x07 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci/* SSC Rx FIFO Status */ 10762306a36Sopenharmony_ci#define SSC_RX_FSTAT_STATUS 0x07 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci/* SSC Clear bit operation */ 11062306a36Sopenharmony_ci#define SSC_CLR_SSCAAS BIT(6) 11162306a36Sopenharmony_ci#define SSC_CLR_SSCSTOP BIT(7) 11262306a36Sopenharmony_ci#define SSC_CLR_SSCARBL BIT(8) 11362306a36Sopenharmony_ci#define SSC_CLR_NACK BIT(10) 11462306a36Sopenharmony_ci#define SSC_CLR_REPSTRT BIT(11) 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci/* SSC Clock Prescaler */ 11762306a36Sopenharmony_ci#define SSC_PRSC_VALUE 0x0f 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define SSC_TXFIFO_SIZE 0x8 12162306a36Sopenharmony_ci#define SSC_RXFIFO_SIZE 0x8 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cienum st_i2c_mode { 12462306a36Sopenharmony_ci I2C_MODE_STANDARD, 12562306a36Sopenharmony_ci I2C_MODE_FAST, 12662306a36Sopenharmony_ci I2C_MODE_END, 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/** 13062306a36Sopenharmony_ci * struct st_i2c_timings - per-Mode tuning parameters 13162306a36Sopenharmony_ci * @rate: I2C bus rate 13262306a36Sopenharmony_ci * @rep_start_hold: I2C repeated start hold time requirement 13362306a36Sopenharmony_ci * @rep_start_setup: I2C repeated start set up time requirement 13462306a36Sopenharmony_ci * @start_hold: I2C start hold time requirement 13562306a36Sopenharmony_ci * @data_setup_time: I2C data set up time requirement 13662306a36Sopenharmony_ci * @stop_setup_time: I2C stop set up time requirement 13762306a36Sopenharmony_ci * @bus_free_time: I2C bus free time requirement 13862306a36Sopenharmony_ci * @sda_pulse_min_limit: I2C SDA pulse mini width limit 13962306a36Sopenharmony_ci */ 14062306a36Sopenharmony_cistruct st_i2c_timings { 14162306a36Sopenharmony_ci u32 rate; 14262306a36Sopenharmony_ci u32 rep_start_hold; 14362306a36Sopenharmony_ci u32 rep_start_setup; 14462306a36Sopenharmony_ci u32 start_hold; 14562306a36Sopenharmony_ci u32 data_setup_time; 14662306a36Sopenharmony_ci u32 stop_setup_time; 14762306a36Sopenharmony_ci u32 bus_free_time; 14862306a36Sopenharmony_ci u32 sda_pulse_min_limit; 14962306a36Sopenharmony_ci}; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci/** 15262306a36Sopenharmony_ci * struct st_i2c_client - client specific data 15362306a36Sopenharmony_ci * @addr: 8-bit slave addr, including r/w bit 15462306a36Sopenharmony_ci * @count: number of bytes to be transfered 15562306a36Sopenharmony_ci * @xfered: number of bytes already transferred 15662306a36Sopenharmony_ci * @buf: data buffer 15762306a36Sopenharmony_ci * @result: result of the transfer 15862306a36Sopenharmony_ci * @stop: last I2C msg to be sent, i.e. STOP to be generated 15962306a36Sopenharmony_ci */ 16062306a36Sopenharmony_cistruct st_i2c_client { 16162306a36Sopenharmony_ci u8 addr; 16262306a36Sopenharmony_ci u32 count; 16362306a36Sopenharmony_ci u32 xfered; 16462306a36Sopenharmony_ci u8 *buf; 16562306a36Sopenharmony_ci int result; 16662306a36Sopenharmony_ci bool stop; 16762306a36Sopenharmony_ci}; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci/** 17062306a36Sopenharmony_ci * struct st_i2c_dev - private data of the controller 17162306a36Sopenharmony_ci * @adap: I2C adapter for this controller 17262306a36Sopenharmony_ci * @dev: device for this controller 17362306a36Sopenharmony_ci * @base: virtual memory area 17462306a36Sopenharmony_ci * @complete: completion of I2C message 17562306a36Sopenharmony_ci * @irq: interrupt line for th controller 17662306a36Sopenharmony_ci * @clk: hw ssc block clock 17762306a36Sopenharmony_ci * @mode: I2C mode of the controller. Standard or Fast only supported 17862306a36Sopenharmony_ci * @scl_min_width_us: SCL line minimum pulse width in us 17962306a36Sopenharmony_ci * @sda_min_width_us: SDA line minimum pulse width in us 18062306a36Sopenharmony_ci * @client: I2C transfert information 18162306a36Sopenharmony_ci * @busy: I2C transfer on-going 18262306a36Sopenharmony_ci */ 18362306a36Sopenharmony_cistruct st_i2c_dev { 18462306a36Sopenharmony_ci struct i2c_adapter adap; 18562306a36Sopenharmony_ci struct device *dev; 18662306a36Sopenharmony_ci void __iomem *base; 18762306a36Sopenharmony_ci struct completion complete; 18862306a36Sopenharmony_ci int irq; 18962306a36Sopenharmony_ci struct clk *clk; 19062306a36Sopenharmony_ci int mode; 19162306a36Sopenharmony_ci u32 scl_min_width_us; 19262306a36Sopenharmony_ci u32 sda_min_width_us; 19362306a36Sopenharmony_ci struct st_i2c_client client; 19462306a36Sopenharmony_ci bool busy; 19562306a36Sopenharmony_ci}; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic inline void st_i2c_set_bits(void __iomem *reg, u32 mask) 19862306a36Sopenharmony_ci{ 19962306a36Sopenharmony_ci writel_relaxed(readl_relaxed(reg) | mask, reg); 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cistatic inline void st_i2c_clr_bits(void __iomem *reg, u32 mask) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci writel_relaxed(readl_relaxed(reg) & ~mask, reg); 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci/* 20862306a36Sopenharmony_ci * From I2C Specifications v0.5. 20962306a36Sopenharmony_ci * 21062306a36Sopenharmony_ci * All the values below have +10% margin added to be 21162306a36Sopenharmony_ci * compatible with some out-of-spec devices, 21262306a36Sopenharmony_ci * like HDMI link of the Toshiba 19AV600 TV. 21362306a36Sopenharmony_ci */ 21462306a36Sopenharmony_cistatic struct st_i2c_timings i2c_timings[] = { 21562306a36Sopenharmony_ci [I2C_MODE_STANDARD] = { 21662306a36Sopenharmony_ci .rate = I2C_MAX_STANDARD_MODE_FREQ, 21762306a36Sopenharmony_ci .rep_start_hold = 4400, 21862306a36Sopenharmony_ci .rep_start_setup = 5170, 21962306a36Sopenharmony_ci .start_hold = 4400, 22062306a36Sopenharmony_ci .data_setup_time = 275, 22162306a36Sopenharmony_ci .stop_setup_time = 4400, 22262306a36Sopenharmony_ci .bus_free_time = 5170, 22362306a36Sopenharmony_ci }, 22462306a36Sopenharmony_ci [I2C_MODE_FAST] = { 22562306a36Sopenharmony_ci .rate = I2C_MAX_FAST_MODE_FREQ, 22662306a36Sopenharmony_ci .rep_start_hold = 660, 22762306a36Sopenharmony_ci .rep_start_setup = 660, 22862306a36Sopenharmony_ci .start_hold = 660, 22962306a36Sopenharmony_ci .data_setup_time = 110, 23062306a36Sopenharmony_ci .stop_setup_time = 660, 23162306a36Sopenharmony_ci .bus_free_time = 1430, 23262306a36Sopenharmony_ci }, 23362306a36Sopenharmony_ci}; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic void st_i2c_flush_rx_fifo(struct st_i2c_dev *i2c_dev) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci int count, i; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* 24062306a36Sopenharmony_ci * Counter only counts up to 7 but fifo size is 8... 24162306a36Sopenharmony_ci * When fifo is full, counter is 0 and RIR bit of status register is 24262306a36Sopenharmony_ci * set 24362306a36Sopenharmony_ci */ 24462306a36Sopenharmony_ci if (readl_relaxed(i2c_dev->base + SSC_STA) & SSC_STA_RIR) 24562306a36Sopenharmony_ci count = SSC_RXFIFO_SIZE; 24662306a36Sopenharmony_ci else 24762306a36Sopenharmony_ci count = readl_relaxed(i2c_dev->base + SSC_RX_FSTAT) & 24862306a36Sopenharmony_ci SSC_RX_FSTAT_STATUS; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci for (i = 0; i < count; i++) 25162306a36Sopenharmony_ci readl_relaxed(i2c_dev->base + SSC_RBUF); 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic void st_i2c_soft_reset(struct st_i2c_dev *i2c_dev) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci /* 25762306a36Sopenharmony_ci * FIFO needs to be emptied before reseting the IP, 25862306a36Sopenharmony_ci * else the controller raises a BUSY error. 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_ci st_i2c_flush_rx_fifo(i2c_dev); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_CTL, SSC_CTL_SR); 26362306a36Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_CTL, SSC_CTL_SR); 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci/** 26762306a36Sopenharmony_ci * st_i2c_hw_config() - Prepare SSC block, calculate and apply tuning timings 26862306a36Sopenharmony_ci * @i2c_dev: Controller's private data 26962306a36Sopenharmony_ci */ 27062306a36Sopenharmony_cistatic void st_i2c_hw_config(struct st_i2c_dev *i2c_dev) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci unsigned long rate; 27362306a36Sopenharmony_ci u32 val, ns_per_clk; 27462306a36Sopenharmony_ci struct st_i2c_timings *t = &i2c_timings[i2c_dev->mode]; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci st_i2c_soft_reset(i2c_dev); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci val = SSC_CLR_REPSTRT | SSC_CLR_NACK | SSC_CLR_SSCARBL | 27962306a36Sopenharmony_ci SSC_CLR_SSCAAS | SSC_CLR_SSCSTOP; 28062306a36Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_CLR); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci /* SSC Control register setup */ 28362306a36Sopenharmony_ci val = SSC_CTL_PO | SSC_CTL_PH | SSC_CTL_HB | SSC_CTL_DATA_WIDTH_9; 28462306a36Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_CTL); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci rate = clk_get_rate(i2c_dev->clk); 28762306a36Sopenharmony_ci ns_per_clk = 1000000000 / rate; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci /* Baudrate */ 29062306a36Sopenharmony_ci val = rate / (2 * t->rate); 29162306a36Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_BRG); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* Pre-scaler baudrate */ 29462306a36Sopenharmony_ci writel_relaxed(1, i2c_dev->base + SSC_PRE_SCALER_BRG); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci /* Enable I2C mode */ 29762306a36Sopenharmony_ci writel_relaxed(SSC_I2C_I2CM, i2c_dev->base + SSC_I2C); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci /* Repeated start hold time */ 30062306a36Sopenharmony_ci val = t->rep_start_hold / ns_per_clk; 30162306a36Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_REP_START_HOLD); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci /* Repeated start set up time */ 30462306a36Sopenharmony_ci val = t->rep_start_setup / ns_per_clk; 30562306a36Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_REP_START_SETUP); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci /* Start hold time */ 30862306a36Sopenharmony_ci val = t->start_hold / ns_per_clk; 30962306a36Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_START_HOLD); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci /* Data set up time */ 31262306a36Sopenharmony_ci val = t->data_setup_time / ns_per_clk; 31362306a36Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_DATA_SETUP); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* Stop set up time */ 31662306a36Sopenharmony_ci val = t->stop_setup_time / ns_per_clk; 31762306a36Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_STOP_SETUP); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci /* Bus free time */ 32062306a36Sopenharmony_ci val = t->bus_free_time / ns_per_clk; 32162306a36Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_BUS_FREE); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci /* Prescalers set up */ 32462306a36Sopenharmony_ci val = rate / 10000000; 32562306a36Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_PRSCALER); 32662306a36Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_PRSCALER_DATAOUT); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci /* Noise suppression witdh */ 32962306a36Sopenharmony_ci val = i2c_dev->scl_min_width_us * rate / 100000000; 33062306a36Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_NOISE_SUPP_WIDTH); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci /* Noise suppression max output data delay width */ 33362306a36Sopenharmony_ci val = i2c_dev->sda_min_width_us * rate / 100000000; 33462306a36Sopenharmony_ci writel_relaxed(val, i2c_dev->base + SSC_NOISE_SUPP_WIDTH_DATAOUT); 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic int st_i2c_recover_bus(struct i2c_adapter *i2c_adap) 33862306a36Sopenharmony_ci{ 33962306a36Sopenharmony_ci struct st_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap); 34062306a36Sopenharmony_ci u32 ctl; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci dev_dbg(i2c_dev->dev, "Trying to recover bus\n"); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* 34562306a36Sopenharmony_ci * SSP IP is dual role SPI/I2C to generate 9 clock pulses 34662306a36Sopenharmony_ci * we switch to SPI node, 9 bit words and write a 0. This 34762306a36Sopenharmony_ci * has been validate with a oscilloscope and is easier 34862306a36Sopenharmony_ci * than switching to GPIO mode. 34962306a36Sopenharmony_ci */ 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci /* Disable interrupts */ 35262306a36Sopenharmony_ci writel_relaxed(0, i2c_dev->base + SSC_IEN); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci st_i2c_hw_config(i2c_dev); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci ctl = SSC_CTL_EN | SSC_CTL_MS | SSC_CTL_EN_RX_FIFO | SSC_CTL_EN_TX_FIFO; 35762306a36Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_CTL, ctl); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_I2CM); 36062306a36Sopenharmony_ci usleep_range(8000, 10000); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci writel_relaxed(0, i2c_dev->base + SSC_TBUF); 36362306a36Sopenharmony_ci usleep_range(2000, 4000); 36462306a36Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_I2CM); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci return 0; 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic int st_i2c_wait_free_bus(struct st_i2c_dev *i2c_dev) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci u32 sta; 37262306a36Sopenharmony_ci int i, ret; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci for (i = 0; i < 10; i++) { 37562306a36Sopenharmony_ci sta = readl_relaxed(i2c_dev->base + SSC_STA); 37662306a36Sopenharmony_ci if (!(sta & SSC_STA_BUSY)) 37762306a36Sopenharmony_ci return 0; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci usleep_range(2000, 4000); 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci dev_err(i2c_dev->dev, "bus not free (status = 0x%08x)\n", sta); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci ret = i2c_recover_bus(&i2c_dev->adap); 38562306a36Sopenharmony_ci if (ret) { 38662306a36Sopenharmony_ci dev_err(i2c_dev->dev, "Failed to recover the bus (%d)\n", ret); 38762306a36Sopenharmony_ci return ret; 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci return -EBUSY; 39162306a36Sopenharmony_ci} 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci/** 39462306a36Sopenharmony_ci * st_i2c_write_tx_fifo() - Write a byte in the Tx FIFO 39562306a36Sopenharmony_ci * @i2c_dev: Controller's private data 39662306a36Sopenharmony_ci * @byte: Data to write in the Tx FIFO 39762306a36Sopenharmony_ci */ 39862306a36Sopenharmony_cistatic inline void st_i2c_write_tx_fifo(struct st_i2c_dev *i2c_dev, u8 byte) 39962306a36Sopenharmony_ci{ 40062306a36Sopenharmony_ci u16 tbuf = byte << 1; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci writel_relaxed(tbuf | 1, i2c_dev->base + SSC_TBUF); 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci/** 40662306a36Sopenharmony_ci * st_i2c_wr_fill_tx_fifo() - Fill the Tx FIFO in write mode 40762306a36Sopenharmony_ci * @i2c_dev: Controller's private data 40862306a36Sopenharmony_ci * 40962306a36Sopenharmony_ci * This functions fills the Tx FIFO with I2C transfert buffer when 41062306a36Sopenharmony_ci * in write mode. 41162306a36Sopenharmony_ci */ 41262306a36Sopenharmony_cistatic void st_i2c_wr_fill_tx_fifo(struct st_i2c_dev *i2c_dev) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 41562306a36Sopenharmony_ci u32 tx_fstat, sta; 41662306a36Sopenharmony_ci int i; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci sta = readl_relaxed(i2c_dev->base + SSC_STA); 41962306a36Sopenharmony_ci if (sta & SSC_STA_TX_FIFO_FULL) 42062306a36Sopenharmony_ci return; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci tx_fstat = readl_relaxed(i2c_dev->base + SSC_TX_FSTAT); 42362306a36Sopenharmony_ci tx_fstat &= SSC_TX_FSTAT_STATUS; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci if (c->count < (SSC_TXFIFO_SIZE - tx_fstat)) 42662306a36Sopenharmony_ci i = c->count; 42762306a36Sopenharmony_ci else 42862306a36Sopenharmony_ci i = SSC_TXFIFO_SIZE - tx_fstat; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci for (; i > 0; i--, c->count--, c->buf++) 43162306a36Sopenharmony_ci st_i2c_write_tx_fifo(i2c_dev, *c->buf); 43262306a36Sopenharmony_ci} 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci/** 43562306a36Sopenharmony_ci * st_i2c_rd_fill_tx_fifo() - Fill the Tx FIFO in read mode 43662306a36Sopenharmony_ci * @i2c_dev: Controller's private data 43762306a36Sopenharmony_ci * @max: Maximum amount of data to fill into the Tx FIFO 43862306a36Sopenharmony_ci * 43962306a36Sopenharmony_ci * This functions fills the Tx FIFO with fixed pattern when 44062306a36Sopenharmony_ci * in read mode to trigger clock. 44162306a36Sopenharmony_ci */ 44262306a36Sopenharmony_cistatic void st_i2c_rd_fill_tx_fifo(struct st_i2c_dev *i2c_dev, int max) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 44562306a36Sopenharmony_ci u32 tx_fstat, sta; 44662306a36Sopenharmony_ci int i; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci sta = readl_relaxed(i2c_dev->base + SSC_STA); 44962306a36Sopenharmony_ci if (sta & SSC_STA_TX_FIFO_FULL) 45062306a36Sopenharmony_ci return; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci tx_fstat = readl_relaxed(i2c_dev->base + SSC_TX_FSTAT); 45362306a36Sopenharmony_ci tx_fstat &= SSC_TX_FSTAT_STATUS; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci if (max < (SSC_TXFIFO_SIZE - tx_fstat)) 45662306a36Sopenharmony_ci i = max; 45762306a36Sopenharmony_ci else 45862306a36Sopenharmony_ci i = SSC_TXFIFO_SIZE - tx_fstat; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci for (; i > 0; i--, c->xfered++) 46162306a36Sopenharmony_ci st_i2c_write_tx_fifo(i2c_dev, 0xff); 46262306a36Sopenharmony_ci} 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_cistatic void st_i2c_read_rx_fifo(struct st_i2c_dev *i2c_dev) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 46762306a36Sopenharmony_ci u32 i, sta; 46862306a36Sopenharmony_ci u16 rbuf; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci sta = readl_relaxed(i2c_dev->base + SSC_STA); 47162306a36Sopenharmony_ci if (sta & SSC_STA_RIR) { 47262306a36Sopenharmony_ci i = SSC_RXFIFO_SIZE; 47362306a36Sopenharmony_ci } else { 47462306a36Sopenharmony_ci i = readl_relaxed(i2c_dev->base + SSC_RX_FSTAT); 47562306a36Sopenharmony_ci i &= SSC_RX_FSTAT_STATUS; 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci for (; (i > 0) && (c->count > 0); i--, c->count--) { 47962306a36Sopenharmony_ci rbuf = readl_relaxed(i2c_dev->base + SSC_RBUF) >> 1; 48062306a36Sopenharmony_ci *c->buf++ = (u8)rbuf & 0xff; 48162306a36Sopenharmony_ci } 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci if (i) { 48462306a36Sopenharmony_ci dev_err(i2c_dev->dev, "Unexpected %d bytes in rx fifo\n", i); 48562306a36Sopenharmony_ci st_i2c_flush_rx_fifo(i2c_dev); 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci} 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci/** 49062306a36Sopenharmony_ci * st_i2c_terminate_xfer() - Send either STOP or REPSTART condition 49162306a36Sopenharmony_ci * @i2c_dev: Controller's private data 49262306a36Sopenharmony_ci */ 49362306a36Sopenharmony_cistatic void st_i2c_terminate_xfer(struct st_i2c_dev *i2c_dev) 49462306a36Sopenharmony_ci{ 49562306a36Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_IEN, SSC_IEN_TEEN); 49862306a36Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STRTG); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci if (c->stop) { 50162306a36Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_IEN, SSC_IEN_STOPEN); 50262306a36Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STOPG); 50362306a36Sopenharmony_ci } else { 50462306a36Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_IEN, SSC_IEN_REPSTRTEN); 50562306a36Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_REPSTRTG); 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci} 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci/** 51062306a36Sopenharmony_ci * st_i2c_handle_write() - Handle FIFO empty interrupt in case of write 51162306a36Sopenharmony_ci * @i2c_dev: Controller's private data 51262306a36Sopenharmony_ci */ 51362306a36Sopenharmony_cistatic void st_i2c_handle_write(struct st_i2c_dev *i2c_dev) 51462306a36Sopenharmony_ci{ 51562306a36Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci st_i2c_flush_rx_fifo(i2c_dev); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci if (!c->count) 52062306a36Sopenharmony_ci /* End of xfer, send stop or repstart */ 52162306a36Sopenharmony_ci st_i2c_terminate_xfer(i2c_dev); 52262306a36Sopenharmony_ci else 52362306a36Sopenharmony_ci st_i2c_wr_fill_tx_fifo(i2c_dev); 52462306a36Sopenharmony_ci} 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci/** 52762306a36Sopenharmony_ci * st_i2c_handle_read() - Handle FIFO empty interrupt in case of read 52862306a36Sopenharmony_ci * @i2c_dev: Controller's private data 52962306a36Sopenharmony_ci */ 53062306a36Sopenharmony_cistatic void st_i2c_handle_read(struct st_i2c_dev *i2c_dev) 53162306a36Sopenharmony_ci{ 53262306a36Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 53362306a36Sopenharmony_ci u32 ien; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci /* Trash the address read back */ 53662306a36Sopenharmony_ci if (!c->xfered) { 53762306a36Sopenharmony_ci readl_relaxed(i2c_dev->base + SSC_RBUF); 53862306a36Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_TXENB); 53962306a36Sopenharmony_ci } else { 54062306a36Sopenharmony_ci st_i2c_read_rx_fifo(i2c_dev); 54162306a36Sopenharmony_ci } 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci if (!c->count) { 54462306a36Sopenharmony_ci /* End of xfer, send stop or repstart */ 54562306a36Sopenharmony_ci st_i2c_terminate_xfer(i2c_dev); 54662306a36Sopenharmony_ci } else if (c->count == 1) { 54762306a36Sopenharmony_ci /* Penultimate byte to xfer, disable ACK gen. */ 54862306a36Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_ACKG); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci /* Last received byte is to be handled by NACK interrupt */ 55162306a36Sopenharmony_ci ien = SSC_IEN_NACKEN | SSC_IEN_ARBLEN; 55262306a36Sopenharmony_ci writel_relaxed(ien, i2c_dev->base + SSC_IEN); 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci st_i2c_rd_fill_tx_fifo(i2c_dev, c->count); 55562306a36Sopenharmony_ci } else { 55662306a36Sopenharmony_ci st_i2c_rd_fill_tx_fifo(i2c_dev, c->count - 1); 55762306a36Sopenharmony_ci } 55862306a36Sopenharmony_ci} 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci/** 56162306a36Sopenharmony_ci * st_i2c_isr_thread() - Interrupt routine 56262306a36Sopenharmony_ci * @irq: interrupt number 56362306a36Sopenharmony_ci * @data: Controller's private data 56462306a36Sopenharmony_ci */ 56562306a36Sopenharmony_cistatic irqreturn_t st_i2c_isr_thread(int irq, void *data) 56662306a36Sopenharmony_ci{ 56762306a36Sopenharmony_ci struct st_i2c_dev *i2c_dev = data; 56862306a36Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 56962306a36Sopenharmony_ci u32 sta, ien; 57062306a36Sopenharmony_ci int it; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci ien = readl_relaxed(i2c_dev->base + SSC_IEN); 57362306a36Sopenharmony_ci sta = readl_relaxed(i2c_dev->base + SSC_STA); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci /* Use __fls() to check error bits first */ 57662306a36Sopenharmony_ci it = __fls(sta & ien); 57762306a36Sopenharmony_ci if (it < 0) { 57862306a36Sopenharmony_ci dev_dbg(i2c_dev->dev, "spurious it (sta=0x%04x, ien=0x%04x)\n", 57962306a36Sopenharmony_ci sta, ien); 58062306a36Sopenharmony_ci return IRQ_NONE; 58162306a36Sopenharmony_ci } 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci switch (1 << it) { 58462306a36Sopenharmony_ci case SSC_STA_TE: 58562306a36Sopenharmony_ci if (c->addr & I2C_M_RD) 58662306a36Sopenharmony_ci st_i2c_handle_read(i2c_dev); 58762306a36Sopenharmony_ci else 58862306a36Sopenharmony_ci st_i2c_handle_write(i2c_dev); 58962306a36Sopenharmony_ci break; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci case SSC_STA_STOP: 59262306a36Sopenharmony_ci case SSC_STA_REPSTRT: 59362306a36Sopenharmony_ci writel_relaxed(0, i2c_dev->base + SSC_IEN); 59462306a36Sopenharmony_ci complete(&i2c_dev->complete); 59562306a36Sopenharmony_ci break; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci case SSC_STA_NACK: 59862306a36Sopenharmony_ci writel_relaxed(SSC_CLR_NACK, i2c_dev->base + SSC_CLR); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci /* Last received byte handled by NACK interrupt */ 60162306a36Sopenharmony_ci if ((c->addr & I2C_M_RD) && (c->count == 1) && (c->xfered)) { 60262306a36Sopenharmony_ci st_i2c_handle_read(i2c_dev); 60362306a36Sopenharmony_ci break; 60462306a36Sopenharmony_ci } 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci it = SSC_IEN_STOPEN | SSC_IEN_ARBLEN; 60762306a36Sopenharmony_ci writel_relaxed(it, i2c_dev->base + SSC_IEN); 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STOPG); 61062306a36Sopenharmony_ci c->result = -EIO; 61162306a36Sopenharmony_ci break; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci case SSC_STA_ARBL: 61462306a36Sopenharmony_ci writel_relaxed(SSC_CLR_SSCARBL, i2c_dev->base + SSC_CLR); 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci it = SSC_IEN_STOPEN | SSC_IEN_ARBLEN; 61762306a36Sopenharmony_ci writel_relaxed(it, i2c_dev->base + SSC_IEN); 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STOPG); 62062306a36Sopenharmony_ci c->result = -EAGAIN; 62162306a36Sopenharmony_ci break; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci default: 62462306a36Sopenharmony_ci dev_err(i2c_dev->dev, 62562306a36Sopenharmony_ci "it %d unhandled (sta=0x%04x)\n", it, sta); 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci /* 62962306a36Sopenharmony_ci * Read IEN register to ensure interrupt mask write is effective 63062306a36Sopenharmony_ci * before re-enabling interrupt at GIC level, and thus avoid spurious 63162306a36Sopenharmony_ci * interrupts. 63262306a36Sopenharmony_ci */ 63362306a36Sopenharmony_ci readl(i2c_dev->base + SSC_IEN); 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci return IRQ_HANDLED; 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci/** 63962306a36Sopenharmony_ci * st_i2c_xfer_msg() - Transfer a single I2C message 64062306a36Sopenharmony_ci * @i2c_dev: Controller's private data 64162306a36Sopenharmony_ci * @msg: I2C message to transfer 64262306a36Sopenharmony_ci * @is_first: first message of the sequence 64362306a36Sopenharmony_ci * @is_last: last message of the sequence 64462306a36Sopenharmony_ci */ 64562306a36Sopenharmony_cistatic int st_i2c_xfer_msg(struct st_i2c_dev *i2c_dev, struct i2c_msg *msg, 64662306a36Sopenharmony_ci bool is_first, bool is_last) 64762306a36Sopenharmony_ci{ 64862306a36Sopenharmony_ci struct st_i2c_client *c = &i2c_dev->client; 64962306a36Sopenharmony_ci u32 ctl, i2c, it; 65062306a36Sopenharmony_ci unsigned long timeout; 65162306a36Sopenharmony_ci int ret; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci c->addr = i2c_8bit_addr_from_msg(msg); 65462306a36Sopenharmony_ci c->buf = msg->buf; 65562306a36Sopenharmony_ci c->count = msg->len; 65662306a36Sopenharmony_ci c->xfered = 0; 65762306a36Sopenharmony_ci c->result = 0; 65862306a36Sopenharmony_ci c->stop = is_last; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci reinit_completion(&i2c_dev->complete); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci ctl = SSC_CTL_EN | SSC_CTL_MS | SSC_CTL_EN_RX_FIFO | SSC_CTL_EN_TX_FIFO; 66362306a36Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_CTL, ctl); 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci i2c = SSC_I2C_TXENB; 66662306a36Sopenharmony_ci if (c->addr & I2C_M_RD) 66762306a36Sopenharmony_ci i2c |= SSC_I2C_ACKG; 66862306a36Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, i2c); 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci /* Write slave address */ 67162306a36Sopenharmony_ci st_i2c_write_tx_fifo(i2c_dev, c->addr); 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci /* Pre-fill Tx fifo with data in case of write */ 67462306a36Sopenharmony_ci if (!(c->addr & I2C_M_RD)) 67562306a36Sopenharmony_ci st_i2c_wr_fill_tx_fifo(i2c_dev); 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci it = SSC_IEN_NACKEN | SSC_IEN_TEEN | SSC_IEN_ARBLEN; 67862306a36Sopenharmony_ci writel_relaxed(it, i2c_dev->base + SSC_IEN); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci if (is_first) { 68162306a36Sopenharmony_ci ret = st_i2c_wait_free_bus(i2c_dev); 68262306a36Sopenharmony_ci if (ret) 68362306a36Sopenharmony_ci return ret; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STRTG); 68662306a36Sopenharmony_ci } 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci timeout = wait_for_completion_timeout(&i2c_dev->complete, 68962306a36Sopenharmony_ci i2c_dev->adap.timeout); 69062306a36Sopenharmony_ci ret = c->result; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci if (!timeout) { 69362306a36Sopenharmony_ci dev_err(i2c_dev->dev, "Write to slave 0x%x timed out\n", 69462306a36Sopenharmony_ci c->addr); 69562306a36Sopenharmony_ci ret = -ETIMEDOUT; 69662306a36Sopenharmony_ci } 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci i2c = SSC_I2C_STOPG | SSC_I2C_REPSTRTG; 69962306a36Sopenharmony_ci st_i2c_clr_bits(i2c_dev->base + SSC_I2C, i2c); 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci writel_relaxed(SSC_CLR_SSCSTOP | SSC_CLR_REPSTRT, 70262306a36Sopenharmony_ci i2c_dev->base + SSC_CLR); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci return ret; 70562306a36Sopenharmony_ci} 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci/** 70862306a36Sopenharmony_ci * st_i2c_xfer() - Transfer a single I2C message 70962306a36Sopenharmony_ci * @i2c_adap: Adapter pointer to the controller 71062306a36Sopenharmony_ci * @msgs: Pointer to data to be written. 71162306a36Sopenharmony_ci * @num: Number of messages to be executed 71262306a36Sopenharmony_ci */ 71362306a36Sopenharmony_cistatic int st_i2c_xfer(struct i2c_adapter *i2c_adap, 71462306a36Sopenharmony_ci struct i2c_msg msgs[], int num) 71562306a36Sopenharmony_ci{ 71662306a36Sopenharmony_ci struct st_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap); 71762306a36Sopenharmony_ci int ret, i; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci i2c_dev->busy = true; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci ret = clk_prepare_enable(i2c_dev->clk); 72262306a36Sopenharmony_ci if (ret) { 72362306a36Sopenharmony_ci dev_err(i2c_dev->dev, "Failed to prepare_enable clock\n"); 72462306a36Sopenharmony_ci return ret; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci pinctrl_pm_select_default_state(i2c_dev->dev); 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci st_i2c_hw_config(i2c_dev); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci for (i = 0; (i < num) && !ret; i++) 73262306a36Sopenharmony_ci ret = st_i2c_xfer_msg(i2c_dev, &msgs[i], i == 0, i == num - 1); 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci pinctrl_pm_select_idle_state(i2c_dev->dev); 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci clk_disable_unprepare(i2c_dev->clk); 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci i2c_dev->busy = false; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci return (ret < 0) ? ret : i; 74162306a36Sopenharmony_ci} 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_cistatic int st_i2c_suspend(struct device *dev) 74462306a36Sopenharmony_ci{ 74562306a36Sopenharmony_ci struct st_i2c_dev *i2c_dev = dev_get_drvdata(dev); 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci if (i2c_dev->busy) 74862306a36Sopenharmony_ci return -EBUSY; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci pinctrl_pm_select_sleep_state(dev); 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci return 0; 75362306a36Sopenharmony_ci} 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_cistatic int st_i2c_resume(struct device *dev) 75662306a36Sopenharmony_ci{ 75762306a36Sopenharmony_ci pinctrl_pm_select_default_state(dev); 75862306a36Sopenharmony_ci /* Go in idle state if available */ 75962306a36Sopenharmony_ci pinctrl_pm_select_idle_state(dev); 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci return 0; 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_cistatic DEFINE_SIMPLE_DEV_PM_OPS(st_i2c_pm, st_i2c_suspend, st_i2c_resume); 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_cistatic u32 st_i2c_func(struct i2c_adapter *adap) 76762306a36Sopenharmony_ci{ 76862306a36Sopenharmony_ci return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 76962306a36Sopenharmony_ci} 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_cistatic const struct i2c_algorithm st_i2c_algo = { 77262306a36Sopenharmony_ci .master_xfer = st_i2c_xfer, 77362306a36Sopenharmony_ci .functionality = st_i2c_func, 77462306a36Sopenharmony_ci}; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_cistatic struct i2c_bus_recovery_info st_i2c_recovery_info = { 77762306a36Sopenharmony_ci .recover_bus = st_i2c_recover_bus, 77862306a36Sopenharmony_ci}; 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_cistatic int st_i2c_of_get_deglitch(struct device_node *np, 78162306a36Sopenharmony_ci struct st_i2c_dev *i2c_dev) 78262306a36Sopenharmony_ci{ 78362306a36Sopenharmony_ci int ret; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci ret = of_property_read_u32(np, "st,i2c-min-scl-pulse-width-us", 78662306a36Sopenharmony_ci &i2c_dev->scl_min_width_us); 78762306a36Sopenharmony_ci if ((ret == -ENODATA) || (ret == -EOVERFLOW)) { 78862306a36Sopenharmony_ci dev_err(i2c_dev->dev, "st,i2c-min-scl-pulse-width-us invalid\n"); 78962306a36Sopenharmony_ci return ret; 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci ret = of_property_read_u32(np, "st,i2c-min-sda-pulse-width-us", 79362306a36Sopenharmony_ci &i2c_dev->sda_min_width_us); 79462306a36Sopenharmony_ci if ((ret == -ENODATA) || (ret == -EOVERFLOW)) { 79562306a36Sopenharmony_ci dev_err(i2c_dev->dev, "st,i2c-min-sda-pulse-width-us invalid\n"); 79662306a36Sopenharmony_ci return ret; 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci return 0; 80062306a36Sopenharmony_ci} 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_cistatic int st_i2c_probe(struct platform_device *pdev) 80362306a36Sopenharmony_ci{ 80462306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 80562306a36Sopenharmony_ci struct st_i2c_dev *i2c_dev; 80662306a36Sopenharmony_ci struct resource *res; 80762306a36Sopenharmony_ci u32 clk_rate; 80862306a36Sopenharmony_ci struct i2c_adapter *adap; 80962306a36Sopenharmony_ci int ret; 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); 81262306a36Sopenharmony_ci if (!i2c_dev) 81362306a36Sopenharmony_ci return -ENOMEM; 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 81662306a36Sopenharmony_ci if (IS_ERR(i2c_dev->base)) 81762306a36Sopenharmony_ci return PTR_ERR(i2c_dev->base); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci i2c_dev->irq = irq_of_parse_and_map(np, 0); 82062306a36Sopenharmony_ci if (!i2c_dev->irq) { 82162306a36Sopenharmony_ci dev_err(&pdev->dev, "IRQ missing or invalid\n"); 82262306a36Sopenharmony_ci return -EINVAL; 82362306a36Sopenharmony_ci } 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci i2c_dev->clk = of_clk_get_by_name(np, "ssc"); 82662306a36Sopenharmony_ci if (IS_ERR(i2c_dev->clk)) { 82762306a36Sopenharmony_ci dev_err(&pdev->dev, "Unable to request clock\n"); 82862306a36Sopenharmony_ci return PTR_ERR(i2c_dev->clk); 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci i2c_dev->mode = I2C_MODE_STANDARD; 83262306a36Sopenharmony_ci ret = of_property_read_u32(np, "clock-frequency", &clk_rate); 83362306a36Sopenharmony_ci if (!ret && (clk_rate == I2C_MAX_FAST_MODE_FREQ)) 83462306a36Sopenharmony_ci i2c_dev->mode = I2C_MODE_FAST; 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci i2c_dev->dev = &pdev->dev; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci ret = devm_request_threaded_irq(&pdev->dev, i2c_dev->irq, 83962306a36Sopenharmony_ci NULL, st_i2c_isr_thread, 84062306a36Sopenharmony_ci IRQF_ONESHOT, pdev->name, i2c_dev); 84162306a36Sopenharmony_ci if (ret) { 84262306a36Sopenharmony_ci dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); 84362306a36Sopenharmony_ci return ret; 84462306a36Sopenharmony_ci } 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci pinctrl_pm_select_default_state(i2c_dev->dev); 84762306a36Sopenharmony_ci /* In case idle state available, select it */ 84862306a36Sopenharmony_ci pinctrl_pm_select_idle_state(i2c_dev->dev); 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci ret = st_i2c_of_get_deglitch(np, i2c_dev); 85162306a36Sopenharmony_ci if (ret) 85262306a36Sopenharmony_ci return ret; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci adap = &i2c_dev->adap; 85562306a36Sopenharmony_ci i2c_set_adapdata(adap, i2c_dev); 85662306a36Sopenharmony_ci snprintf(adap->name, sizeof(adap->name), "ST I2C(%pa)", &res->start); 85762306a36Sopenharmony_ci adap->owner = THIS_MODULE; 85862306a36Sopenharmony_ci adap->timeout = 2 * HZ; 85962306a36Sopenharmony_ci adap->retries = 0; 86062306a36Sopenharmony_ci adap->algo = &st_i2c_algo; 86162306a36Sopenharmony_ci adap->bus_recovery_info = &st_i2c_recovery_info; 86262306a36Sopenharmony_ci adap->dev.parent = &pdev->dev; 86362306a36Sopenharmony_ci adap->dev.of_node = pdev->dev.of_node; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci init_completion(&i2c_dev->complete); 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci ret = i2c_add_adapter(adap); 86862306a36Sopenharmony_ci if (ret) 86962306a36Sopenharmony_ci return ret; 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci platform_set_drvdata(pdev, i2c_dev); 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci dev_info(i2c_dev->dev, "%s initialized\n", adap->name); 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci return 0; 87662306a36Sopenharmony_ci} 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_cistatic void st_i2c_remove(struct platform_device *pdev) 87962306a36Sopenharmony_ci{ 88062306a36Sopenharmony_ci struct st_i2c_dev *i2c_dev = platform_get_drvdata(pdev); 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci i2c_del_adapter(&i2c_dev->adap); 88362306a36Sopenharmony_ci} 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_cistatic const struct of_device_id st_i2c_match[] = { 88662306a36Sopenharmony_ci { .compatible = "st,comms-ssc-i2c", }, 88762306a36Sopenharmony_ci { .compatible = "st,comms-ssc4-i2c", }, 88862306a36Sopenharmony_ci {}, 88962306a36Sopenharmony_ci}; 89062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, st_i2c_match); 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_cistatic struct platform_driver st_i2c_driver = { 89362306a36Sopenharmony_ci .driver = { 89462306a36Sopenharmony_ci .name = "st-i2c", 89562306a36Sopenharmony_ci .of_match_table = st_i2c_match, 89662306a36Sopenharmony_ci .pm = pm_sleep_ptr(&st_i2c_pm), 89762306a36Sopenharmony_ci }, 89862306a36Sopenharmony_ci .probe = st_i2c_probe, 89962306a36Sopenharmony_ci .remove_new = st_i2c_remove, 90062306a36Sopenharmony_ci}; 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_cimodule_platform_driver(st_i2c_driver); 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ciMODULE_AUTHOR("Maxime Coquelin <maxime.coquelin@st.com>"); 90562306a36Sopenharmony_ciMODULE_DESCRIPTION("STMicroelectronics I2C driver"); 90662306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 907