18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2013 STMicroelectronics
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * I2C master mode controller driver, used in STMicroelectronics devices.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Author: Maxime Coquelin <maxime.coquelin@st.com>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/clk.h>
118c2ecf20Sopenharmony_ci#include <linux/delay.h>
128c2ecf20Sopenharmony_ci#include <linux/err.h>
138c2ecf20Sopenharmony_ci#include <linux/i2c.h>
148c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
158c2ecf20Sopenharmony_ci#include <linux/io.h>
168c2ecf20Sopenharmony_ci#include <linux/module.h>
178c2ecf20Sopenharmony_ci#include <linux/of_address.h>
188c2ecf20Sopenharmony_ci#include <linux/of_irq.h>
198c2ecf20Sopenharmony_ci#include <linux/of.h>
208c2ecf20Sopenharmony_ci#include <linux/pinctrl/consumer.h>
218c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/* SSC registers */
248c2ecf20Sopenharmony_ci#define SSC_BRG				0x000
258c2ecf20Sopenharmony_ci#define SSC_TBUF			0x004
268c2ecf20Sopenharmony_ci#define SSC_RBUF			0x008
278c2ecf20Sopenharmony_ci#define SSC_CTL				0x00C
288c2ecf20Sopenharmony_ci#define SSC_IEN				0x010
298c2ecf20Sopenharmony_ci#define SSC_STA				0x014
308c2ecf20Sopenharmony_ci#define SSC_I2C				0x018
318c2ecf20Sopenharmony_ci#define SSC_SLAD			0x01C
328c2ecf20Sopenharmony_ci#define SSC_REP_START_HOLD		0x020
338c2ecf20Sopenharmony_ci#define SSC_START_HOLD			0x024
348c2ecf20Sopenharmony_ci#define SSC_REP_START_SETUP		0x028
358c2ecf20Sopenharmony_ci#define SSC_DATA_SETUP			0x02C
368c2ecf20Sopenharmony_ci#define SSC_STOP_SETUP			0x030
378c2ecf20Sopenharmony_ci#define SSC_BUS_FREE			0x034
388c2ecf20Sopenharmony_ci#define SSC_TX_FSTAT			0x038
398c2ecf20Sopenharmony_ci#define SSC_RX_FSTAT			0x03C
408c2ecf20Sopenharmony_ci#define SSC_PRE_SCALER_BRG		0x040
418c2ecf20Sopenharmony_ci#define SSC_CLR				0x080
428c2ecf20Sopenharmony_ci#define SSC_NOISE_SUPP_WIDTH		0x100
438c2ecf20Sopenharmony_ci#define SSC_PRSCALER			0x104
448c2ecf20Sopenharmony_ci#define SSC_NOISE_SUPP_WIDTH_DATAOUT	0x108
458c2ecf20Sopenharmony_ci#define SSC_PRSCALER_DATAOUT		0x10c
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/* SSC Control */
488c2ecf20Sopenharmony_ci#define SSC_CTL_DATA_WIDTH_9		0x8
498c2ecf20Sopenharmony_ci#define SSC_CTL_DATA_WIDTH_MSK		0xf
508c2ecf20Sopenharmony_ci#define SSC_CTL_BM			0xf
518c2ecf20Sopenharmony_ci#define SSC_CTL_HB			BIT(4)
528c2ecf20Sopenharmony_ci#define SSC_CTL_PH			BIT(5)
538c2ecf20Sopenharmony_ci#define SSC_CTL_PO			BIT(6)
548c2ecf20Sopenharmony_ci#define SSC_CTL_SR			BIT(7)
558c2ecf20Sopenharmony_ci#define SSC_CTL_MS			BIT(8)
568c2ecf20Sopenharmony_ci#define SSC_CTL_EN			BIT(9)
578c2ecf20Sopenharmony_ci#define SSC_CTL_LPB			BIT(10)
588c2ecf20Sopenharmony_ci#define SSC_CTL_EN_TX_FIFO		BIT(11)
598c2ecf20Sopenharmony_ci#define SSC_CTL_EN_RX_FIFO		BIT(12)
608c2ecf20Sopenharmony_ci#define SSC_CTL_EN_CLST_RX		BIT(13)
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/* SSC Interrupt Enable */
638c2ecf20Sopenharmony_ci#define SSC_IEN_RIEN			BIT(0)
648c2ecf20Sopenharmony_ci#define SSC_IEN_TIEN			BIT(1)
658c2ecf20Sopenharmony_ci#define SSC_IEN_TEEN			BIT(2)
668c2ecf20Sopenharmony_ci#define SSC_IEN_REEN			BIT(3)
678c2ecf20Sopenharmony_ci#define SSC_IEN_PEEN			BIT(4)
688c2ecf20Sopenharmony_ci#define SSC_IEN_AASEN			BIT(6)
698c2ecf20Sopenharmony_ci#define SSC_IEN_STOPEN			BIT(7)
708c2ecf20Sopenharmony_ci#define SSC_IEN_ARBLEN			BIT(8)
718c2ecf20Sopenharmony_ci#define SSC_IEN_NACKEN			BIT(10)
728c2ecf20Sopenharmony_ci#define SSC_IEN_REPSTRTEN		BIT(11)
738c2ecf20Sopenharmony_ci#define SSC_IEN_TX_FIFO_HALF		BIT(12)
748c2ecf20Sopenharmony_ci#define SSC_IEN_RX_FIFO_HALF_FULL	BIT(14)
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci/* SSC Status */
778c2ecf20Sopenharmony_ci#define SSC_STA_RIR			BIT(0)
788c2ecf20Sopenharmony_ci#define SSC_STA_TIR			BIT(1)
798c2ecf20Sopenharmony_ci#define SSC_STA_TE			BIT(2)
808c2ecf20Sopenharmony_ci#define SSC_STA_RE			BIT(3)
818c2ecf20Sopenharmony_ci#define SSC_STA_PE			BIT(4)
828c2ecf20Sopenharmony_ci#define SSC_STA_CLST			BIT(5)
838c2ecf20Sopenharmony_ci#define SSC_STA_AAS			BIT(6)
848c2ecf20Sopenharmony_ci#define SSC_STA_STOP			BIT(7)
858c2ecf20Sopenharmony_ci#define SSC_STA_ARBL			BIT(8)
868c2ecf20Sopenharmony_ci#define SSC_STA_BUSY			BIT(9)
878c2ecf20Sopenharmony_ci#define SSC_STA_NACK			BIT(10)
888c2ecf20Sopenharmony_ci#define SSC_STA_REPSTRT			BIT(11)
898c2ecf20Sopenharmony_ci#define SSC_STA_TX_FIFO_HALF		BIT(12)
908c2ecf20Sopenharmony_ci#define SSC_STA_TX_FIFO_FULL		BIT(13)
918c2ecf20Sopenharmony_ci#define SSC_STA_RX_FIFO_HALF		BIT(14)
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci/* SSC I2C Control */
948c2ecf20Sopenharmony_ci#define SSC_I2C_I2CM			BIT(0)
958c2ecf20Sopenharmony_ci#define SSC_I2C_STRTG			BIT(1)
968c2ecf20Sopenharmony_ci#define SSC_I2C_STOPG			BIT(2)
978c2ecf20Sopenharmony_ci#define SSC_I2C_ACKG			BIT(3)
988c2ecf20Sopenharmony_ci#define SSC_I2C_AD10			BIT(4)
998c2ecf20Sopenharmony_ci#define SSC_I2C_TXENB			BIT(5)
1008c2ecf20Sopenharmony_ci#define SSC_I2C_REPSTRTG		BIT(11)
1018c2ecf20Sopenharmony_ci#define SSC_I2C_SLAVE_DISABLE		BIT(12)
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci/* SSC Tx FIFO Status */
1048c2ecf20Sopenharmony_ci#define SSC_TX_FSTAT_STATUS		0x07
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci/* SSC Rx FIFO Status */
1078c2ecf20Sopenharmony_ci#define SSC_RX_FSTAT_STATUS		0x07
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci/* SSC Clear bit operation */
1108c2ecf20Sopenharmony_ci#define SSC_CLR_SSCAAS			BIT(6)
1118c2ecf20Sopenharmony_ci#define SSC_CLR_SSCSTOP			BIT(7)
1128c2ecf20Sopenharmony_ci#define SSC_CLR_SSCARBL			BIT(8)
1138c2ecf20Sopenharmony_ci#define SSC_CLR_NACK			BIT(10)
1148c2ecf20Sopenharmony_ci#define SSC_CLR_REPSTRT			BIT(11)
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci/* SSC Clock Prescaler */
1178c2ecf20Sopenharmony_ci#define SSC_PRSC_VALUE			0x0f
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci#define SSC_TXFIFO_SIZE			0x8
1218c2ecf20Sopenharmony_ci#define SSC_RXFIFO_SIZE			0x8
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cienum st_i2c_mode {
1248c2ecf20Sopenharmony_ci	I2C_MODE_STANDARD,
1258c2ecf20Sopenharmony_ci	I2C_MODE_FAST,
1268c2ecf20Sopenharmony_ci	I2C_MODE_END,
1278c2ecf20Sopenharmony_ci};
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci/**
1308c2ecf20Sopenharmony_ci * struct st_i2c_timings - per-Mode tuning parameters
1318c2ecf20Sopenharmony_ci * @rate: I2C bus rate
1328c2ecf20Sopenharmony_ci * @rep_start_hold: I2C repeated start hold time requirement
1338c2ecf20Sopenharmony_ci * @rep_start_setup: I2C repeated start set up time requirement
1348c2ecf20Sopenharmony_ci * @start_hold: I2C start hold time requirement
1358c2ecf20Sopenharmony_ci * @data_setup_time: I2C data set up time requirement
1368c2ecf20Sopenharmony_ci * @stop_setup_time: I2C stop set up time requirement
1378c2ecf20Sopenharmony_ci * @bus_free_time: I2C bus free time requirement
1388c2ecf20Sopenharmony_ci * @sda_pulse_min_limit: I2C SDA pulse mini width limit
1398c2ecf20Sopenharmony_ci */
1408c2ecf20Sopenharmony_cistruct st_i2c_timings {
1418c2ecf20Sopenharmony_ci	u32 rate;
1428c2ecf20Sopenharmony_ci	u32 rep_start_hold;
1438c2ecf20Sopenharmony_ci	u32 rep_start_setup;
1448c2ecf20Sopenharmony_ci	u32 start_hold;
1458c2ecf20Sopenharmony_ci	u32 data_setup_time;
1468c2ecf20Sopenharmony_ci	u32 stop_setup_time;
1478c2ecf20Sopenharmony_ci	u32 bus_free_time;
1488c2ecf20Sopenharmony_ci	u32 sda_pulse_min_limit;
1498c2ecf20Sopenharmony_ci};
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci/**
1528c2ecf20Sopenharmony_ci * struct st_i2c_client - client specific data
1538c2ecf20Sopenharmony_ci * @addr: 8-bit slave addr, including r/w bit
1548c2ecf20Sopenharmony_ci * @count: number of bytes to be transfered
1558c2ecf20Sopenharmony_ci * @xfered: number of bytes already transferred
1568c2ecf20Sopenharmony_ci * @buf: data buffer
1578c2ecf20Sopenharmony_ci * @result: result of the transfer
1588c2ecf20Sopenharmony_ci * @stop: last I2C msg to be sent, i.e. STOP to be generated
1598c2ecf20Sopenharmony_ci */
1608c2ecf20Sopenharmony_cistruct st_i2c_client {
1618c2ecf20Sopenharmony_ci	u8	addr;
1628c2ecf20Sopenharmony_ci	u32	count;
1638c2ecf20Sopenharmony_ci	u32	xfered;
1648c2ecf20Sopenharmony_ci	u8	*buf;
1658c2ecf20Sopenharmony_ci	int	result;
1668c2ecf20Sopenharmony_ci	bool	stop;
1678c2ecf20Sopenharmony_ci};
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci/**
1708c2ecf20Sopenharmony_ci * struct st_i2c_dev - private data of the controller
1718c2ecf20Sopenharmony_ci * @adap: I2C adapter for this controller
1728c2ecf20Sopenharmony_ci * @dev: device for this controller
1738c2ecf20Sopenharmony_ci * @base: virtual memory area
1748c2ecf20Sopenharmony_ci * @complete: completion of I2C message
1758c2ecf20Sopenharmony_ci * @irq: interrupt line for th controller
1768c2ecf20Sopenharmony_ci * @clk: hw ssc block clock
1778c2ecf20Sopenharmony_ci * @mode: I2C mode of the controller. Standard or Fast only supported
1788c2ecf20Sopenharmony_ci * @scl_min_width_us: SCL line minimum pulse width in us
1798c2ecf20Sopenharmony_ci * @sda_min_width_us: SDA line minimum pulse width in us
1808c2ecf20Sopenharmony_ci * @client: I2C transfert information
1818c2ecf20Sopenharmony_ci * @busy: I2C transfer on-going
1828c2ecf20Sopenharmony_ci */
1838c2ecf20Sopenharmony_cistruct st_i2c_dev {
1848c2ecf20Sopenharmony_ci	struct i2c_adapter	adap;
1858c2ecf20Sopenharmony_ci	struct device		*dev;
1868c2ecf20Sopenharmony_ci	void __iomem		*base;
1878c2ecf20Sopenharmony_ci	struct completion	complete;
1888c2ecf20Sopenharmony_ci	int			irq;
1898c2ecf20Sopenharmony_ci	struct clk		*clk;
1908c2ecf20Sopenharmony_ci	int			mode;
1918c2ecf20Sopenharmony_ci	u32			scl_min_width_us;
1928c2ecf20Sopenharmony_ci	u32			sda_min_width_us;
1938c2ecf20Sopenharmony_ci	struct st_i2c_client	client;
1948c2ecf20Sopenharmony_ci	bool			busy;
1958c2ecf20Sopenharmony_ci};
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cistatic inline void st_i2c_set_bits(void __iomem *reg, u32 mask)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	writel_relaxed(readl_relaxed(reg) | mask, reg);
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistatic inline void st_i2c_clr_bits(void __iomem *reg, u32 mask)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	writel_relaxed(readl_relaxed(reg) & ~mask, reg);
2058c2ecf20Sopenharmony_ci}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci/*
2088c2ecf20Sopenharmony_ci * From I2C Specifications v0.5.
2098c2ecf20Sopenharmony_ci *
2108c2ecf20Sopenharmony_ci * All the values below have +10% margin added to be
2118c2ecf20Sopenharmony_ci * compatible with some out-of-spec devices,
2128c2ecf20Sopenharmony_ci * like HDMI link of the Toshiba 19AV600 TV.
2138c2ecf20Sopenharmony_ci */
2148c2ecf20Sopenharmony_cistatic struct st_i2c_timings i2c_timings[] = {
2158c2ecf20Sopenharmony_ci	[I2C_MODE_STANDARD] = {
2168c2ecf20Sopenharmony_ci		.rate			= I2C_MAX_STANDARD_MODE_FREQ,
2178c2ecf20Sopenharmony_ci		.rep_start_hold		= 4400,
2188c2ecf20Sopenharmony_ci		.rep_start_setup	= 5170,
2198c2ecf20Sopenharmony_ci		.start_hold		= 4400,
2208c2ecf20Sopenharmony_ci		.data_setup_time	= 275,
2218c2ecf20Sopenharmony_ci		.stop_setup_time	= 4400,
2228c2ecf20Sopenharmony_ci		.bus_free_time		= 5170,
2238c2ecf20Sopenharmony_ci	},
2248c2ecf20Sopenharmony_ci	[I2C_MODE_FAST] = {
2258c2ecf20Sopenharmony_ci		.rate			= I2C_MAX_FAST_MODE_FREQ,
2268c2ecf20Sopenharmony_ci		.rep_start_hold		= 660,
2278c2ecf20Sopenharmony_ci		.rep_start_setup	= 660,
2288c2ecf20Sopenharmony_ci		.start_hold		= 660,
2298c2ecf20Sopenharmony_ci		.data_setup_time	= 110,
2308c2ecf20Sopenharmony_ci		.stop_setup_time	= 660,
2318c2ecf20Sopenharmony_ci		.bus_free_time		= 1430,
2328c2ecf20Sopenharmony_ci	},
2338c2ecf20Sopenharmony_ci};
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic void st_i2c_flush_rx_fifo(struct st_i2c_dev *i2c_dev)
2368c2ecf20Sopenharmony_ci{
2378c2ecf20Sopenharmony_ci	int count, i;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	/*
2408c2ecf20Sopenharmony_ci	 * Counter only counts up to 7 but fifo size is 8...
2418c2ecf20Sopenharmony_ci	 * When fifo is full, counter is 0 and RIR bit of status register is
2428c2ecf20Sopenharmony_ci	 * set
2438c2ecf20Sopenharmony_ci	 */
2448c2ecf20Sopenharmony_ci	if (readl_relaxed(i2c_dev->base + SSC_STA) & SSC_STA_RIR)
2458c2ecf20Sopenharmony_ci		count = SSC_RXFIFO_SIZE;
2468c2ecf20Sopenharmony_ci	else
2478c2ecf20Sopenharmony_ci		count = readl_relaxed(i2c_dev->base + SSC_RX_FSTAT) &
2488c2ecf20Sopenharmony_ci			SSC_RX_FSTAT_STATUS;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	for (i = 0; i < count; i++)
2518c2ecf20Sopenharmony_ci		readl_relaxed(i2c_dev->base + SSC_RBUF);
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cistatic void st_i2c_soft_reset(struct st_i2c_dev *i2c_dev)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	/*
2578c2ecf20Sopenharmony_ci	 * FIFO needs to be emptied before reseting the IP,
2588c2ecf20Sopenharmony_ci	 * else the controller raises a BUSY error.
2598c2ecf20Sopenharmony_ci	 */
2608c2ecf20Sopenharmony_ci	st_i2c_flush_rx_fifo(i2c_dev);
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	st_i2c_set_bits(i2c_dev->base + SSC_CTL, SSC_CTL_SR);
2638c2ecf20Sopenharmony_ci	st_i2c_clr_bits(i2c_dev->base + SSC_CTL, SSC_CTL_SR);
2648c2ecf20Sopenharmony_ci}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci/**
2678c2ecf20Sopenharmony_ci * st_i2c_hw_config() - Prepare SSC block, calculate and apply tuning timings
2688c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data
2698c2ecf20Sopenharmony_ci */
2708c2ecf20Sopenharmony_cistatic void st_i2c_hw_config(struct st_i2c_dev *i2c_dev)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	unsigned long rate;
2738c2ecf20Sopenharmony_ci	u32 val, ns_per_clk;
2748c2ecf20Sopenharmony_ci	struct st_i2c_timings *t = &i2c_timings[i2c_dev->mode];
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	st_i2c_soft_reset(i2c_dev);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	val = SSC_CLR_REPSTRT | SSC_CLR_NACK | SSC_CLR_SSCARBL |
2798c2ecf20Sopenharmony_ci		SSC_CLR_SSCAAS | SSC_CLR_SSCSTOP;
2808c2ecf20Sopenharmony_ci	writel_relaxed(val, i2c_dev->base + SSC_CLR);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	/* SSC Control register setup */
2838c2ecf20Sopenharmony_ci	val = SSC_CTL_PO | SSC_CTL_PH | SSC_CTL_HB | SSC_CTL_DATA_WIDTH_9;
2848c2ecf20Sopenharmony_ci	writel_relaxed(val, i2c_dev->base + SSC_CTL);
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	rate = clk_get_rate(i2c_dev->clk);
2878c2ecf20Sopenharmony_ci	ns_per_clk = 1000000000 / rate;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	/* Baudrate */
2908c2ecf20Sopenharmony_ci	val = rate / (2 * t->rate);
2918c2ecf20Sopenharmony_ci	writel_relaxed(val, i2c_dev->base + SSC_BRG);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	/* Pre-scaler baudrate */
2948c2ecf20Sopenharmony_ci	writel_relaxed(1, i2c_dev->base + SSC_PRE_SCALER_BRG);
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	/* Enable I2C mode */
2978c2ecf20Sopenharmony_ci	writel_relaxed(SSC_I2C_I2CM, i2c_dev->base + SSC_I2C);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	/* Repeated start hold time */
3008c2ecf20Sopenharmony_ci	val = t->rep_start_hold / ns_per_clk;
3018c2ecf20Sopenharmony_ci	writel_relaxed(val, i2c_dev->base + SSC_REP_START_HOLD);
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	/* Repeated start set up time */
3048c2ecf20Sopenharmony_ci	val = t->rep_start_setup / ns_per_clk;
3058c2ecf20Sopenharmony_ci	writel_relaxed(val, i2c_dev->base + SSC_REP_START_SETUP);
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	/* Start hold time */
3088c2ecf20Sopenharmony_ci	val = t->start_hold / ns_per_clk;
3098c2ecf20Sopenharmony_ci	writel_relaxed(val, i2c_dev->base + SSC_START_HOLD);
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	/* Data set up time */
3128c2ecf20Sopenharmony_ci	val = t->data_setup_time / ns_per_clk;
3138c2ecf20Sopenharmony_ci	writel_relaxed(val, i2c_dev->base + SSC_DATA_SETUP);
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	/* Stop set up time */
3168c2ecf20Sopenharmony_ci	val = t->stop_setup_time / ns_per_clk;
3178c2ecf20Sopenharmony_ci	writel_relaxed(val, i2c_dev->base + SSC_STOP_SETUP);
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	/* Bus free time */
3208c2ecf20Sopenharmony_ci	val = t->bus_free_time / ns_per_clk;
3218c2ecf20Sopenharmony_ci	writel_relaxed(val, i2c_dev->base + SSC_BUS_FREE);
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	/* Prescalers set up */
3248c2ecf20Sopenharmony_ci	val = rate / 10000000;
3258c2ecf20Sopenharmony_ci	writel_relaxed(val, i2c_dev->base + SSC_PRSCALER);
3268c2ecf20Sopenharmony_ci	writel_relaxed(val, i2c_dev->base + SSC_PRSCALER_DATAOUT);
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	/* Noise suppression witdh */
3298c2ecf20Sopenharmony_ci	val = i2c_dev->scl_min_width_us * rate / 100000000;
3308c2ecf20Sopenharmony_ci	writel_relaxed(val, i2c_dev->base + SSC_NOISE_SUPP_WIDTH);
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	/* Noise suppression max output data delay width */
3338c2ecf20Sopenharmony_ci	val = i2c_dev->sda_min_width_us * rate / 100000000;
3348c2ecf20Sopenharmony_ci	writel_relaxed(val, i2c_dev->base + SSC_NOISE_SUPP_WIDTH_DATAOUT);
3358c2ecf20Sopenharmony_ci}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_cistatic int st_i2c_recover_bus(struct i2c_adapter *i2c_adap)
3388c2ecf20Sopenharmony_ci{
3398c2ecf20Sopenharmony_ci	struct st_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
3408c2ecf20Sopenharmony_ci	u32 ctl;
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	dev_dbg(i2c_dev->dev, "Trying to recover bus\n");
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	/*
3458c2ecf20Sopenharmony_ci	 * SSP IP is dual role SPI/I2C to generate 9 clock pulses
3468c2ecf20Sopenharmony_ci	 * we switch to SPI node, 9 bit words and write a 0. This
3478c2ecf20Sopenharmony_ci	 * has been validate with a oscilloscope and is easier
3488c2ecf20Sopenharmony_ci	 * than switching to GPIO mode.
3498c2ecf20Sopenharmony_ci	 */
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	/* Disable interrupts */
3528c2ecf20Sopenharmony_ci	writel_relaxed(0, i2c_dev->base + SSC_IEN);
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	st_i2c_hw_config(i2c_dev);
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	ctl = SSC_CTL_EN | SSC_CTL_MS |	SSC_CTL_EN_RX_FIFO | SSC_CTL_EN_TX_FIFO;
3578c2ecf20Sopenharmony_ci	st_i2c_set_bits(i2c_dev->base + SSC_CTL, ctl);
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_I2CM);
3608c2ecf20Sopenharmony_ci	usleep_range(8000, 10000);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	writel_relaxed(0, i2c_dev->base + SSC_TBUF);
3638c2ecf20Sopenharmony_ci	usleep_range(2000, 4000);
3648c2ecf20Sopenharmony_ci	st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_I2CM);
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	return 0;
3678c2ecf20Sopenharmony_ci}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_cistatic int st_i2c_wait_free_bus(struct st_i2c_dev *i2c_dev)
3708c2ecf20Sopenharmony_ci{
3718c2ecf20Sopenharmony_ci	u32 sta;
3728c2ecf20Sopenharmony_ci	int i, ret;
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	for (i = 0; i < 10; i++) {
3758c2ecf20Sopenharmony_ci		sta = readl_relaxed(i2c_dev->base + SSC_STA);
3768c2ecf20Sopenharmony_ci		if (!(sta & SSC_STA_BUSY))
3778c2ecf20Sopenharmony_ci			return 0;
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci		usleep_range(2000, 4000);
3808c2ecf20Sopenharmony_ci	}
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	dev_err(i2c_dev->dev, "bus not free (status = 0x%08x)\n", sta);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	ret = i2c_recover_bus(&i2c_dev->adap);
3858c2ecf20Sopenharmony_ci	if (ret) {
3868c2ecf20Sopenharmony_ci		dev_err(i2c_dev->dev, "Failed to recover the bus (%d)\n", ret);
3878c2ecf20Sopenharmony_ci		return ret;
3888c2ecf20Sopenharmony_ci	}
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	return -EBUSY;
3918c2ecf20Sopenharmony_ci}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci/**
3948c2ecf20Sopenharmony_ci * st_i2c_write_tx_fifo() - Write a byte in the Tx FIFO
3958c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data
3968c2ecf20Sopenharmony_ci * @byte: Data to write in the Tx FIFO
3978c2ecf20Sopenharmony_ci */
3988c2ecf20Sopenharmony_cistatic inline void st_i2c_write_tx_fifo(struct st_i2c_dev *i2c_dev, u8 byte)
3998c2ecf20Sopenharmony_ci{
4008c2ecf20Sopenharmony_ci	u16 tbuf = byte << 1;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	writel_relaxed(tbuf | 1, i2c_dev->base + SSC_TBUF);
4038c2ecf20Sopenharmony_ci}
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci/**
4068c2ecf20Sopenharmony_ci * st_i2c_wr_fill_tx_fifo() - Fill the Tx FIFO in write mode
4078c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data
4088c2ecf20Sopenharmony_ci *
4098c2ecf20Sopenharmony_ci * This functions fills the Tx FIFO with I2C transfert buffer when
4108c2ecf20Sopenharmony_ci * in write mode.
4118c2ecf20Sopenharmony_ci */
4128c2ecf20Sopenharmony_cistatic void st_i2c_wr_fill_tx_fifo(struct st_i2c_dev *i2c_dev)
4138c2ecf20Sopenharmony_ci{
4148c2ecf20Sopenharmony_ci	struct st_i2c_client *c = &i2c_dev->client;
4158c2ecf20Sopenharmony_ci	u32 tx_fstat, sta;
4168c2ecf20Sopenharmony_ci	int i;
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	sta = readl_relaxed(i2c_dev->base + SSC_STA);
4198c2ecf20Sopenharmony_ci	if (sta & SSC_STA_TX_FIFO_FULL)
4208c2ecf20Sopenharmony_ci		return;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	tx_fstat = readl_relaxed(i2c_dev->base + SSC_TX_FSTAT);
4238c2ecf20Sopenharmony_ci	tx_fstat &= SSC_TX_FSTAT_STATUS;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	if (c->count < (SSC_TXFIFO_SIZE - tx_fstat))
4268c2ecf20Sopenharmony_ci		i = c->count;
4278c2ecf20Sopenharmony_ci	else
4288c2ecf20Sopenharmony_ci		i = SSC_TXFIFO_SIZE - tx_fstat;
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	for (; i > 0; i--, c->count--, c->buf++)
4318c2ecf20Sopenharmony_ci		st_i2c_write_tx_fifo(i2c_dev, *c->buf);
4328c2ecf20Sopenharmony_ci}
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci/**
4358c2ecf20Sopenharmony_ci * st_i2c_rd_fill_tx_fifo() - Fill the Tx FIFO in read mode
4368c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data
4378c2ecf20Sopenharmony_ci * @max: Maximum amount of data to fill into the Tx FIFO
4388c2ecf20Sopenharmony_ci *
4398c2ecf20Sopenharmony_ci * This functions fills the Tx FIFO with fixed pattern when
4408c2ecf20Sopenharmony_ci * in read mode to trigger clock.
4418c2ecf20Sopenharmony_ci */
4428c2ecf20Sopenharmony_cistatic void st_i2c_rd_fill_tx_fifo(struct st_i2c_dev *i2c_dev, int max)
4438c2ecf20Sopenharmony_ci{
4448c2ecf20Sopenharmony_ci	struct st_i2c_client *c = &i2c_dev->client;
4458c2ecf20Sopenharmony_ci	u32 tx_fstat, sta;
4468c2ecf20Sopenharmony_ci	int i;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	sta = readl_relaxed(i2c_dev->base + SSC_STA);
4498c2ecf20Sopenharmony_ci	if (sta & SSC_STA_TX_FIFO_FULL)
4508c2ecf20Sopenharmony_ci		return;
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	tx_fstat = readl_relaxed(i2c_dev->base + SSC_TX_FSTAT);
4538c2ecf20Sopenharmony_ci	tx_fstat &= SSC_TX_FSTAT_STATUS;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	if (max < (SSC_TXFIFO_SIZE - tx_fstat))
4568c2ecf20Sopenharmony_ci		i = max;
4578c2ecf20Sopenharmony_ci	else
4588c2ecf20Sopenharmony_ci		i = SSC_TXFIFO_SIZE - tx_fstat;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	for (; i > 0; i--, c->xfered++)
4618c2ecf20Sopenharmony_ci		st_i2c_write_tx_fifo(i2c_dev, 0xff);
4628c2ecf20Sopenharmony_ci}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_cistatic void st_i2c_read_rx_fifo(struct st_i2c_dev *i2c_dev)
4658c2ecf20Sopenharmony_ci{
4668c2ecf20Sopenharmony_ci	struct st_i2c_client *c = &i2c_dev->client;
4678c2ecf20Sopenharmony_ci	u32 i, sta;
4688c2ecf20Sopenharmony_ci	u16 rbuf;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	sta = readl_relaxed(i2c_dev->base + SSC_STA);
4718c2ecf20Sopenharmony_ci	if (sta & SSC_STA_RIR) {
4728c2ecf20Sopenharmony_ci		i = SSC_RXFIFO_SIZE;
4738c2ecf20Sopenharmony_ci	} else {
4748c2ecf20Sopenharmony_ci		i = readl_relaxed(i2c_dev->base + SSC_RX_FSTAT);
4758c2ecf20Sopenharmony_ci		i &= SSC_RX_FSTAT_STATUS;
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	for (; (i > 0) && (c->count > 0); i--, c->count--) {
4798c2ecf20Sopenharmony_ci		rbuf = readl_relaxed(i2c_dev->base + SSC_RBUF) >> 1;
4808c2ecf20Sopenharmony_ci		*c->buf++ = (u8)rbuf & 0xff;
4818c2ecf20Sopenharmony_ci	}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	if (i) {
4848c2ecf20Sopenharmony_ci		dev_err(i2c_dev->dev, "Unexpected %d bytes in rx fifo\n", i);
4858c2ecf20Sopenharmony_ci		st_i2c_flush_rx_fifo(i2c_dev);
4868c2ecf20Sopenharmony_ci	}
4878c2ecf20Sopenharmony_ci}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci/**
4908c2ecf20Sopenharmony_ci * st_i2c_terminate_xfer() - Send either STOP or REPSTART condition
4918c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data
4928c2ecf20Sopenharmony_ci */
4938c2ecf20Sopenharmony_cistatic void st_i2c_terminate_xfer(struct st_i2c_dev *i2c_dev)
4948c2ecf20Sopenharmony_ci{
4958c2ecf20Sopenharmony_ci	struct st_i2c_client *c = &i2c_dev->client;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	st_i2c_clr_bits(i2c_dev->base + SSC_IEN, SSC_IEN_TEEN);
4988c2ecf20Sopenharmony_ci	st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STRTG);
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	if (c->stop) {
5018c2ecf20Sopenharmony_ci		st_i2c_set_bits(i2c_dev->base + SSC_IEN, SSC_IEN_STOPEN);
5028c2ecf20Sopenharmony_ci		st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STOPG);
5038c2ecf20Sopenharmony_ci	} else {
5048c2ecf20Sopenharmony_ci		st_i2c_set_bits(i2c_dev->base + SSC_IEN, SSC_IEN_REPSTRTEN);
5058c2ecf20Sopenharmony_ci		st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_REPSTRTG);
5068c2ecf20Sopenharmony_ci	}
5078c2ecf20Sopenharmony_ci}
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci/**
5108c2ecf20Sopenharmony_ci * st_i2c_handle_write() - Handle FIFO empty interrupt in case of write
5118c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data
5128c2ecf20Sopenharmony_ci */
5138c2ecf20Sopenharmony_cistatic void st_i2c_handle_write(struct st_i2c_dev *i2c_dev)
5148c2ecf20Sopenharmony_ci{
5158c2ecf20Sopenharmony_ci	struct st_i2c_client *c = &i2c_dev->client;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	st_i2c_flush_rx_fifo(i2c_dev);
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	if (!c->count)
5208c2ecf20Sopenharmony_ci		/* End of xfer, send stop or repstart */
5218c2ecf20Sopenharmony_ci		st_i2c_terminate_xfer(i2c_dev);
5228c2ecf20Sopenharmony_ci	else
5238c2ecf20Sopenharmony_ci		st_i2c_wr_fill_tx_fifo(i2c_dev);
5248c2ecf20Sopenharmony_ci}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci/**
5278c2ecf20Sopenharmony_ci * st_i2c_handle_write() - Handle FIFO enmpty interrupt in case of read
5288c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data
5298c2ecf20Sopenharmony_ci */
5308c2ecf20Sopenharmony_cistatic void st_i2c_handle_read(struct st_i2c_dev *i2c_dev)
5318c2ecf20Sopenharmony_ci{
5328c2ecf20Sopenharmony_ci	struct st_i2c_client *c = &i2c_dev->client;
5338c2ecf20Sopenharmony_ci	u32 ien;
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	/* Trash the address read back */
5368c2ecf20Sopenharmony_ci	if (!c->xfered) {
5378c2ecf20Sopenharmony_ci		readl_relaxed(i2c_dev->base + SSC_RBUF);
5388c2ecf20Sopenharmony_ci		st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_TXENB);
5398c2ecf20Sopenharmony_ci	} else {
5408c2ecf20Sopenharmony_ci		st_i2c_read_rx_fifo(i2c_dev);
5418c2ecf20Sopenharmony_ci	}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	if (!c->count) {
5448c2ecf20Sopenharmony_ci		/* End of xfer, send stop or repstart */
5458c2ecf20Sopenharmony_ci		st_i2c_terminate_xfer(i2c_dev);
5468c2ecf20Sopenharmony_ci	} else if (c->count == 1) {
5478c2ecf20Sopenharmony_ci		/* Penultimate byte to xfer, disable ACK gen. */
5488c2ecf20Sopenharmony_ci		st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_ACKG);
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci		/* Last received byte is to be handled by NACK interrupt */
5518c2ecf20Sopenharmony_ci		ien = SSC_IEN_NACKEN | SSC_IEN_ARBLEN;
5528c2ecf20Sopenharmony_ci		writel_relaxed(ien, i2c_dev->base + SSC_IEN);
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci		st_i2c_rd_fill_tx_fifo(i2c_dev, c->count);
5558c2ecf20Sopenharmony_ci	} else {
5568c2ecf20Sopenharmony_ci		st_i2c_rd_fill_tx_fifo(i2c_dev, c->count - 1);
5578c2ecf20Sopenharmony_ci	}
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci/**
5618c2ecf20Sopenharmony_ci * st_i2c_isr() - Interrupt routine
5628c2ecf20Sopenharmony_ci * @irq: interrupt number
5638c2ecf20Sopenharmony_ci * @data: Controller's private data
5648c2ecf20Sopenharmony_ci */
5658c2ecf20Sopenharmony_cistatic irqreturn_t st_i2c_isr_thread(int irq, void *data)
5668c2ecf20Sopenharmony_ci{
5678c2ecf20Sopenharmony_ci	struct st_i2c_dev *i2c_dev = data;
5688c2ecf20Sopenharmony_ci	struct st_i2c_client *c = &i2c_dev->client;
5698c2ecf20Sopenharmony_ci	u32 sta, ien;
5708c2ecf20Sopenharmony_ci	int it;
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	ien = readl_relaxed(i2c_dev->base + SSC_IEN);
5738c2ecf20Sopenharmony_ci	sta = readl_relaxed(i2c_dev->base + SSC_STA);
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	/* Use __fls() to check error bits first */
5768c2ecf20Sopenharmony_ci	it = __fls(sta & ien);
5778c2ecf20Sopenharmony_ci	if (it < 0) {
5788c2ecf20Sopenharmony_ci		dev_dbg(i2c_dev->dev, "spurious it (sta=0x%04x, ien=0x%04x)\n",
5798c2ecf20Sopenharmony_ci				sta, ien);
5808c2ecf20Sopenharmony_ci		return IRQ_NONE;
5818c2ecf20Sopenharmony_ci	}
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	switch (1 << it) {
5848c2ecf20Sopenharmony_ci	case SSC_STA_TE:
5858c2ecf20Sopenharmony_ci		if (c->addr & I2C_M_RD)
5868c2ecf20Sopenharmony_ci			st_i2c_handle_read(i2c_dev);
5878c2ecf20Sopenharmony_ci		else
5888c2ecf20Sopenharmony_ci			st_i2c_handle_write(i2c_dev);
5898c2ecf20Sopenharmony_ci		break;
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	case SSC_STA_STOP:
5928c2ecf20Sopenharmony_ci	case SSC_STA_REPSTRT:
5938c2ecf20Sopenharmony_ci		writel_relaxed(0, i2c_dev->base + SSC_IEN);
5948c2ecf20Sopenharmony_ci		complete(&i2c_dev->complete);
5958c2ecf20Sopenharmony_ci		break;
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	case SSC_STA_NACK:
5988c2ecf20Sopenharmony_ci		writel_relaxed(SSC_CLR_NACK, i2c_dev->base + SSC_CLR);
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci		/* Last received byte handled by NACK interrupt */
6018c2ecf20Sopenharmony_ci		if ((c->addr & I2C_M_RD) && (c->count == 1) && (c->xfered)) {
6028c2ecf20Sopenharmony_ci			st_i2c_handle_read(i2c_dev);
6038c2ecf20Sopenharmony_ci			break;
6048c2ecf20Sopenharmony_ci		}
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci		it = SSC_IEN_STOPEN | SSC_IEN_ARBLEN;
6078c2ecf20Sopenharmony_ci		writel_relaxed(it, i2c_dev->base + SSC_IEN);
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci		st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STOPG);
6108c2ecf20Sopenharmony_ci		c->result = -EIO;
6118c2ecf20Sopenharmony_ci		break;
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	case SSC_STA_ARBL:
6148c2ecf20Sopenharmony_ci		writel_relaxed(SSC_CLR_SSCARBL, i2c_dev->base + SSC_CLR);
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci		it = SSC_IEN_STOPEN | SSC_IEN_ARBLEN;
6178c2ecf20Sopenharmony_ci		writel_relaxed(it, i2c_dev->base + SSC_IEN);
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci		st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STOPG);
6208c2ecf20Sopenharmony_ci		c->result = -EAGAIN;
6218c2ecf20Sopenharmony_ci		break;
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	default:
6248c2ecf20Sopenharmony_ci		dev_err(i2c_dev->dev,
6258c2ecf20Sopenharmony_ci				"it %d unhandled (sta=0x%04x)\n", it, sta);
6268c2ecf20Sopenharmony_ci	}
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	/*
6298c2ecf20Sopenharmony_ci	 * Read IEN register to ensure interrupt mask write is effective
6308c2ecf20Sopenharmony_ci	 * before re-enabling interrupt at GIC level, and thus avoid spurious
6318c2ecf20Sopenharmony_ci	 * interrupts.
6328c2ecf20Sopenharmony_ci	 */
6338c2ecf20Sopenharmony_ci	readl(i2c_dev->base + SSC_IEN);
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
6368c2ecf20Sopenharmony_ci}
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci/**
6398c2ecf20Sopenharmony_ci * st_i2c_xfer_msg() - Transfer a single I2C message
6408c2ecf20Sopenharmony_ci * @i2c_dev: Controller's private data
6418c2ecf20Sopenharmony_ci * @msg: I2C message to transfer
6428c2ecf20Sopenharmony_ci * @is_first: first message of the sequence
6438c2ecf20Sopenharmony_ci * @is_last: last message of the sequence
6448c2ecf20Sopenharmony_ci */
6458c2ecf20Sopenharmony_cistatic int st_i2c_xfer_msg(struct st_i2c_dev *i2c_dev, struct i2c_msg *msg,
6468c2ecf20Sopenharmony_ci			    bool is_first, bool is_last)
6478c2ecf20Sopenharmony_ci{
6488c2ecf20Sopenharmony_ci	struct st_i2c_client *c = &i2c_dev->client;
6498c2ecf20Sopenharmony_ci	u32 ctl, i2c, it;
6508c2ecf20Sopenharmony_ci	unsigned long timeout;
6518c2ecf20Sopenharmony_ci	int ret;
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	c->addr		= i2c_8bit_addr_from_msg(msg);
6548c2ecf20Sopenharmony_ci	c->buf		= msg->buf;
6558c2ecf20Sopenharmony_ci	c->count	= msg->len;
6568c2ecf20Sopenharmony_ci	c->xfered	= 0;
6578c2ecf20Sopenharmony_ci	c->result	= 0;
6588c2ecf20Sopenharmony_ci	c->stop		= is_last;
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	reinit_completion(&i2c_dev->complete);
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	ctl = SSC_CTL_EN | SSC_CTL_MS |	SSC_CTL_EN_RX_FIFO | SSC_CTL_EN_TX_FIFO;
6638c2ecf20Sopenharmony_ci	st_i2c_set_bits(i2c_dev->base + SSC_CTL, ctl);
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	i2c = SSC_I2C_TXENB;
6668c2ecf20Sopenharmony_ci	if (c->addr & I2C_M_RD)
6678c2ecf20Sopenharmony_ci		i2c |= SSC_I2C_ACKG;
6688c2ecf20Sopenharmony_ci	st_i2c_set_bits(i2c_dev->base + SSC_I2C, i2c);
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	/* Write slave address */
6718c2ecf20Sopenharmony_ci	st_i2c_write_tx_fifo(i2c_dev, c->addr);
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	/* Pre-fill Tx fifo with data in case of write */
6748c2ecf20Sopenharmony_ci	if (!(c->addr & I2C_M_RD))
6758c2ecf20Sopenharmony_ci		st_i2c_wr_fill_tx_fifo(i2c_dev);
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	it = SSC_IEN_NACKEN | SSC_IEN_TEEN | SSC_IEN_ARBLEN;
6788c2ecf20Sopenharmony_ci	writel_relaxed(it, i2c_dev->base + SSC_IEN);
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	if (is_first) {
6818c2ecf20Sopenharmony_ci		ret = st_i2c_wait_free_bus(i2c_dev);
6828c2ecf20Sopenharmony_ci		if (ret)
6838c2ecf20Sopenharmony_ci			return ret;
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci		st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STRTG);
6868c2ecf20Sopenharmony_ci	}
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	timeout = wait_for_completion_timeout(&i2c_dev->complete,
6898c2ecf20Sopenharmony_ci			i2c_dev->adap.timeout);
6908c2ecf20Sopenharmony_ci	ret = c->result;
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	if (!timeout) {
6938c2ecf20Sopenharmony_ci		dev_err(i2c_dev->dev, "Write to slave 0x%x timed out\n",
6948c2ecf20Sopenharmony_ci				c->addr);
6958c2ecf20Sopenharmony_ci		ret = -ETIMEDOUT;
6968c2ecf20Sopenharmony_ci	}
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	i2c = SSC_I2C_STOPG | SSC_I2C_REPSTRTG;
6998c2ecf20Sopenharmony_ci	st_i2c_clr_bits(i2c_dev->base + SSC_I2C, i2c);
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	writel_relaxed(SSC_CLR_SSCSTOP | SSC_CLR_REPSTRT,
7028c2ecf20Sopenharmony_ci			i2c_dev->base + SSC_CLR);
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	return ret;
7058c2ecf20Sopenharmony_ci}
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci/**
7088c2ecf20Sopenharmony_ci * st_i2c_xfer() - Transfer a single I2C message
7098c2ecf20Sopenharmony_ci * @i2c_adap: Adapter pointer to the controller
7108c2ecf20Sopenharmony_ci * @msgs: Pointer to data to be written.
7118c2ecf20Sopenharmony_ci * @num: Number of messages to be executed
7128c2ecf20Sopenharmony_ci */
7138c2ecf20Sopenharmony_cistatic int st_i2c_xfer(struct i2c_adapter *i2c_adap,
7148c2ecf20Sopenharmony_ci			struct i2c_msg msgs[], int num)
7158c2ecf20Sopenharmony_ci{
7168c2ecf20Sopenharmony_ci	struct st_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
7178c2ecf20Sopenharmony_ci	int ret, i;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	i2c_dev->busy = true;
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(i2c_dev->clk);
7228c2ecf20Sopenharmony_ci	if (ret) {
7238c2ecf20Sopenharmony_ci		dev_err(i2c_dev->dev, "Failed to prepare_enable clock\n");
7248c2ecf20Sopenharmony_ci		return ret;
7258c2ecf20Sopenharmony_ci	}
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	pinctrl_pm_select_default_state(i2c_dev->dev);
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	st_i2c_hw_config(i2c_dev);
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	for (i = 0; (i < num) && !ret; i++)
7328c2ecf20Sopenharmony_ci		ret = st_i2c_xfer_msg(i2c_dev, &msgs[i], i == 0, i == num - 1);
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	pinctrl_pm_select_idle_state(i2c_dev->dev);
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	clk_disable_unprepare(i2c_dev->clk);
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	i2c_dev->busy = false;
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	return (ret < 0) ? ret : i;
7418c2ecf20Sopenharmony_ci}
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
7448c2ecf20Sopenharmony_cistatic int st_i2c_suspend(struct device *dev)
7458c2ecf20Sopenharmony_ci{
7468c2ecf20Sopenharmony_ci	struct st_i2c_dev *i2c_dev = dev_get_drvdata(dev);
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	if (i2c_dev->busy)
7498c2ecf20Sopenharmony_ci		return -EBUSY;
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	pinctrl_pm_select_sleep_state(dev);
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	return 0;
7548c2ecf20Sopenharmony_ci}
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_cistatic int st_i2c_resume(struct device *dev)
7578c2ecf20Sopenharmony_ci{
7588c2ecf20Sopenharmony_ci	pinctrl_pm_select_default_state(dev);
7598c2ecf20Sopenharmony_ci	/* Go in idle state if available */
7608c2ecf20Sopenharmony_ci	pinctrl_pm_select_idle_state(dev);
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	return 0;
7638c2ecf20Sopenharmony_ci}
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(st_i2c_pm, st_i2c_suspend, st_i2c_resume);
7668c2ecf20Sopenharmony_ci#define ST_I2C_PM	(&st_i2c_pm)
7678c2ecf20Sopenharmony_ci#else
7688c2ecf20Sopenharmony_ci#define ST_I2C_PM	NULL
7698c2ecf20Sopenharmony_ci#endif
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_cistatic u32 st_i2c_func(struct i2c_adapter *adap)
7728c2ecf20Sopenharmony_ci{
7738c2ecf20Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
7748c2ecf20Sopenharmony_ci}
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_cistatic const struct i2c_algorithm st_i2c_algo = {
7778c2ecf20Sopenharmony_ci	.master_xfer = st_i2c_xfer,
7788c2ecf20Sopenharmony_ci	.functionality = st_i2c_func,
7798c2ecf20Sopenharmony_ci};
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_cistatic struct i2c_bus_recovery_info st_i2c_recovery_info = {
7828c2ecf20Sopenharmony_ci	.recover_bus = st_i2c_recover_bus,
7838c2ecf20Sopenharmony_ci};
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_cistatic int st_i2c_of_get_deglitch(struct device_node *np,
7868c2ecf20Sopenharmony_ci		struct st_i2c_dev *i2c_dev)
7878c2ecf20Sopenharmony_ci{
7888c2ecf20Sopenharmony_ci	int ret;
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	ret = of_property_read_u32(np, "st,i2c-min-scl-pulse-width-us",
7918c2ecf20Sopenharmony_ci			&i2c_dev->scl_min_width_us);
7928c2ecf20Sopenharmony_ci	if ((ret == -ENODATA) || (ret == -EOVERFLOW)) {
7938c2ecf20Sopenharmony_ci		dev_err(i2c_dev->dev, "st,i2c-min-scl-pulse-width-us invalid\n");
7948c2ecf20Sopenharmony_ci		return ret;
7958c2ecf20Sopenharmony_ci	}
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	ret = of_property_read_u32(np, "st,i2c-min-sda-pulse-width-us",
7988c2ecf20Sopenharmony_ci			&i2c_dev->sda_min_width_us);
7998c2ecf20Sopenharmony_ci	if ((ret == -ENODATA) || (ret == -EOVERFLOW)) {
8008c2ecf20Sopenharmony_ci		dev_err(i2c_dev->dev, "st,i2c-min-sda-pulse-width-us invalid\n");
8018c2ecf20Sopenharmony_ci		return ret;
8028c2ecf20Sopenharmony_ci	}
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci	return 0;
8058c2ecf20Sopenharmony_ci}
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_cistatic int st_i2c_probe(struct platform_device *pdev)
8088c2ecf20Sopenharmony_ci{
8098c2ecf20Sopenharmony_ci	struct device_node *np = pdev->dev.of_node;
8108c2ecf20Sopenharmony_ci	struct st_i2c_dev *i2c_dev;
8118c2ecf20Sopenharmony_ci	struct resource *res;
8128c2ecf20Sopenharmony_ci	u32 clk_rate;
8138c2ecf20Sopenharmony_ci	struct i2c_adapter *adap;
8148c2ecf20Sopenharmony_ci	int ret;
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci	i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
8178c2ecf20Sopenharmony_ci	if (!i2c_dev)
8188c2ecf20Sopenharmony_ci		return -ENOMEM;
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
8218c2ecf20Sopenharmony_ci	i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
8228c2ecf20Sopenharmony_ci	if (IS_ERR(i2c_dev->base))
8238c2ecf20Sopenharmony_ci		return PTR_ERR(i2c_dev->base);
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	i2c_dev->irq = irq_of_parse_and_map(np, 0);
8268c2ecf20Sopenharmony_ci	if (!i2c_dev->irq) {
8278c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "IRQ missing or invalid\n");
8288c2ecf20Sopenharmony_ci		return -EINVAL;
8298c2ecf20Sopenharmony_ci	}
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	i2c_dev->clk = of_clk_get_by_name(np, "ssc");
8328c2ecf20Sopenharmony_ci	if (IS_ERR(i2c_dev->clk)) {
8338c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Unable to request clock\n");
8348c2ecf20Sopenharmony_ci		return PTR_ERR(i2c_dev->clk);
8358c2ecf20Sopenharmony_ci	}
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci	i2c_dev->mode = I2C_MODE_STANDARD;
8388c2ecf20Sopenharmony_ci	ret = of_property_read_u32(np, "clock-frequency", &clk_rate);
8398c2ecf20Sopenharmony_ci	if (!ret && (clk_rate == I2C_MAX_FAST_MODE_FREQ))
8408c2ecf20Sopenharmony_ci		i2c_dev->mode = I2C_MODE_FAST;
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	i2c_dev->dev = &pdev->dev;
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	ret = devm_request_threaded_irq(&pdev->dev, i2c_dev->irq,
8458c2ecf20Sopenharmony_ci			NULL, st_i2c_isr_thread,
8468c2ecf20Sopenharmony_ci			IRQF_ONESHOT, pdev->name, i2c_dev);
8478c2ecf20Sopenharmony_ci	if (ret) {
8488c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
8498c2ecf20Sopenharmony_ci		return ret;
8508c2ecf20Sopenharmony_ci	}
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	pinctrl_pm_select_default_state(i2c_dev->dev);
8538c2ecf20Sopenharmony_ci	/* In case idle state available, select it */
8548c2ecf20Sopenharmony_ci	pinctrl_pm_select_idle_state(i2c_dev->dev);
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	ret = st_i2c_of_get_deglitch(np, i2c_dev);
8578c2ecf20Sopenharmony_ci	if (ret)
8588c2ecf20Sopenharmony_ci		return ret;
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	adap = &i2c_dev->adap;
8618c2ecf20Sopenharmony_ci	i2c_set_adapdata(adap, i2c_dev);
8628c2ecf20Sopenharmony_ci	snprintf(adap->name, sizeof(adap->name), "ST I2C(%pa)", &res->start);
8638c2ecf20Sopenharmony_ci	adap->owner = THIS_MODULE;
8648c2ecf20Sopenharmony_ci	adap->timeout = 2 * HZ;
8658c2ecf20Sopenharmony_ci	adap->retries = 0;
8668c2ecf20Sopenharmony_ci	adap->algo = &st_i2c_algo;
8678c2ecf20Sopenharmony_ci	adap->bus_recovery_info = &st_i2c_recovery_info;
8688c2ecf20Sopenharmony_ci	adap->dev.parent = &pdev->dev;
8698c2ecf20Sopenharmony_ci	adap->dev.of_node = pdev->dev.of_node;
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	init_completion(&i2c_dev->complete);
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	ret = i2c_add_adapter(adap);
8748c2ecf20Sopenharmony_ci	if (ret)
8758c2ecf20Sopenharmony_ci		return ret;
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, i2c_dev);
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci	dev_info(i2c_dev->dev, "%s initialized\n", adap->name);
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci	return 0;
8828c2ecf20Sopenharmony_ci}
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_cistatic int st_i2c_remove(struct platform_device *pdev)
8858c2ecf20Sopenharmony_ci{
8868c2ecf20Sopenharmony_ci	struct st_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci	i2c_del_adapter(&i2c_dev->adap);
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	return 0;
8918c2ecf20Sopenharmony_ci}
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_cistatic const struct of_device_id st_i2c_match[] = {
8948c2ecf20Sopenharmony_ci	{ .compatible = "st,comms-ssc-i2c", },
8958c2ecf20Sopenharmony_ci	{ .compatible = "st,comms-ssc4-i2c", },
8968c2ecf20Sopenharmony_ci	{},
8978c2ecf20Sopenharmony_ci};
8988c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, st_i2c_match);
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_cistatic struct platform_driver st_i2c_driver = {
9018c2ecf20Sopenharmony_ci	.driver = {
9028c2ecf20Sopenharmony_ci		.name = "st-i2c",
9038c2ecf20Sopenharmony_ci		.of_match_table = st_i2c_match,
9048c2ecf20Sopenharmony_ci		.pm = ST_I2C_PM,
9058c2ecf20Sopenharmony_ci	},
9068c2ecf20Sopenharmony_ci	.probe = st_i2c_probe,
9078c2ecf20Sopenharmony_ci	.remove = st_i2c_remove,
9088c2ecf20Sopenharmony_ci};
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_cimodule_platform_driver(st_i2c_driver);
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ciMODULE_AUTHOR("Maxime Coquelin <maxime.coquelin@st.com>");
9138c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("STMicroelectronics I2C driver");
9148c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
915