xref: /linux/drivers/i2c/busses/i2c-cgbc.c (revision e70140ba0d2b1a30467d4af6bcfe761327b9ec95)
16894f640SThomas Richard // SPDX-License-Identifier: GPL-2.0-or-later
26894f640SThomas Richard /*
36894f640SThomas Richard  * Congatec Board Controller I2C busses driver
46894f640SThomas Richard  *
56894f640SThomas Richard  * Copyright (C) 2024 Bootlin
66894f640SThomas Richard  * Author: Thomas Richard <thomas.richard@bootlin.com>
76894f640SThomas Richard  */
86894f640SThomas Richard 
96894f640SThomas Richard #include <linux/i2c.h>
106894f640SThomas Richard #include <linux/iopoll.h>
116894f640SThomas Richard #include <linux/mfd/cgbc.h>
126894f640SThomas Richard #include <linux/module.h>
136894f640SThomas Richard #include <linux/platform_device.h>
146894f640SThomas Richard 
156894f640SThomas Richard #define CGBC_I2C_PRIMARY_BUS_ID	0
166894f640SThomas Richard #define CGBC_I2C_PM_BUS_ID	4
176894f640SThomas Richard 
186894f640SThomas Richard #define CGBC_I2C_CMD_START	0x40
196894f640SThomas Richard #define CGBC_I2C_CMD_STAT	0x48
206894f640SThomas Richard #define CGBC_I2C_CMD_DATA	0x50
216894f640SThomas Richard #define CGBC_I2C_CMD_SPEED	0x58
226894f640SThomas Richard 
236894f640SThomas Richard #define CGBC_I2C_STAT_IDL	0x00
246894f640SThomas Richard #define CGBC_I2C_STAT_DAT	0x01
256894f640SThomas Richard #define CGBC_I2C_STAT_BUSY	0x02
266894f640SThomas Richard 
276894f640SThomas Richard #define CGBC_I2C_START	0x80
286894f640SThomas Richard #define CGBC_I2C_STOP	0x40
296894f640SThomas Richard 
306894f640SThomas Richard #define CGBC_I2C_LAST_ACK  0x80    /* send ACK on last read byte */
316894f640SThomas Richard 
326894f640SThomas Richard /*
336894f640SThomas Richard  * Reference code defines 1kHz as min freq and 6.1MHz as max freq.
346894f640SThomas Richard  * But in practice, the board controller limits the frequency to 1MHz, and the
356894f640SThomas Richard  * 1kHz is not functional (minimal working freq is 50kHz).
366894f640SThomas Richard  * So use these values as limits.
376894f640SThomas Richard  */
386894f640SThomas Richard #define CGBC_I2C_FREQ_MIN_HZ	50000	/* 50 kHz */
396894f640SThomas Richard #define CGBC_I2C_FREQ_MAX_HZ	1000000 /* 1 MHz */
406894f640SThomas Richard 
416894f640SThomas Richard #define CGBC_I2C_FREQ_UNIT_1KHZ		0x40
426894f640SThomas Richard #define CGBC_I2C_FREQ_UNIT_10KHZ	0x80
436894f640SThomas Richard #define CGBC_I2C_FREQ_UNIT_100KHZ	0xC0
446894f640SThomas Richard 
456894f640SThomas Richard #define CGBC_I2C_FREQ_UNIT_MASK		0xC0
466894f640SThomas Richard #define CGBC_I2C_FREQ_VALUE_MASK	0x3F
476894f640SThomas Richard 
486894f640SThomas Richard #define CGBC_I2C_READ_MAX_LEN	31
496894f640SThomas Richard #define CGBC_I2C_WRITE_MAX_LEN	32
506894f640SThomas Richard 
516894f640SThomas Richard #define CGBC_I2C_CMD_HEADER_SIZE	4
526894f640SThomas Richard #define CGBC_I2C_CMD_SIZE		(CGBC_I2C_CMD_HEADER_SIZE + CGBC_I2C_WRITE_MAX_LEN)
536894f640SThomas Richard 
546894f640SThomas Richard enum cgbc_i2c_state {
556894f640SThomas Richard 	CGBC_I2C_STATE_DONE = 0,
566894f640SThomas Richard 	CGBC_I2C_STATE_INIT,
576894f640SThomas Richard 	CGBC_I2C_STATE_START,
586894f640SThomas Richard 	CGBC_I2C_STATE_READ,
596894f640SThomas Richard 	CGBC_I2C_STATE_WRITE,
606894f640SThomas Richard 	CGBC_I2C_STATE_ERROR,
616894f640SThomas Richard };
626894f640SThomas Richard 
636894f640SThomas Richard struct i2c_algo_cgbc_data {
646894f640SThomas Richard 	u8		bus_id;
656894f640SThomas Richard 	unsigned long	read_maxtime_us;
666894f640SThomas Richard };
676894f640SThomas Richard 
686894f640SThomas Richard struct cgbc_i2c_data {
696894f640SThomas Richard 	struct device		*dev;
706894f640SThomas Richard 	struct cgbc_device_data *cgbc;
716894f640SThomas Richard 	struct i2c_adapter      adap;
726894f640SThomas Richard 	struct i2c_msg		*msg;
736894f640SThomas Richard 	int			nmsgs;
746894f640SThomas Richard 	int			pos;
756894f640SThomas Richard 	enum cgbc_i2c_state	state;
766894f640SThomas Richard };
776894f640SThomas Richard 
786894f640SThomas Richard struct cgbc_i2c_transfer {
796894f640SThomas Richard 	u8 bus_id;
806894f640SThomas Richard 	bool start;
816894f640SThomas Richard 	bool stop;
826894f640SThomas Richard 	bool last_ack;
836894f640SThomas Richard 	u8 read;
846894f640SThomas Richard 	u8 write;
856894f640SThomas Richard 	u8 addr;
866894f640SThomas Richard 	u8 data[CGBC_I2C_WRITE_MAX_LEN];
876894f640SThomas Richard };
886894f640SThomas Richard 
cgbc_i2c_freq_to_reg(unsigned int bus_frequency)896894f640SThomas Richard static u8 cgbc_i2c_freq_to_reg(unsigned int bus_frequency)
906894f640SThomas Richard {
916894f640SThomas Richard 	u8 reg;
926894f640SThomas Richard 
936894f640SThomas Richard 	if (bus_frequency <= 10000)
946894f640SThomas Richard 		reg = CGBC_I2C_FREQ_UNIT_1KHZ | (bus_frequency / 1000);
956894f640SThomas Richard 	else if (bus_frequency <= 100000)
966894f640SThomas Richard 		reg = CGBC_I2C_FREQ_UNIT_10KHZ | (bus_frequency / 10000);
976894f640SThomas Richard 	else
986894f640SThomas Richard 		reg = CGBC_I2C_FREQ_UNIT_100KHZ | (bus_frequency / 100000);
996894f640SThomas Richard 
1006894f640SThomas Richard 	return reg;
1016894f640SThomas Richard }
1026894f640SThomas Richard 
cgbc_i2c_reg_to_freq(u8 reg)1036894f640SThomas Richard static unsigned int cgbc_i2c_reg_to_freq(u8 reg)
1046894f640SThomas Richard {
1056894f640SThomas Richard 	unsigned int freq = reg & CGBC_I2C_FREQ_VALUE_MASK;
1066894f640SThomas Richard 	u8 unit = reg & CGBC_I2C_FREQ_UNIT_MASK;
1076894f640SThomas Richard 
1086894f640SThomas Richard 	if (unit == CGBC_I2C_FREQ_UNIT_100KHZ)
1096894f640SThomas Richard 		return freq * 100000;
1106894f640SThomas Richard 	else if (unit == CGBC_I2C_FREQ_UNIT_10KHZ)
1116894f640SThomas Richard 		return freq * 10000;
1126894f640SThomas Richard 	else
1136894f640SThomas Richard 		return freq * 1000;
1146894f640SThomas Richard }
1156894f640SThomas Richard 
cgbc_i2c_get_status(struct i2c_adapter * adap)1166894f640SThomas Richard static int cgbc_i2c_get_status(struct i2c_adapter *adap)
1176894f640SThomas Richard {
1186894f640SThomas Richard 	struct i2c_algo_cgbc_data *algo_data = adap->algo_data;
1196894f640SThomas Richard 	struct cgbc_i2c_data *i2c = i2c_get_adapdata(adap);
1206894f640SThomas Richard 	struct cgbc_device_data *cgbc = i2c->cgbc;
1216894f640SThomas Richard 	u8 cmd = CGBC_I2C_CMD_STAT | algo_data->bus_id;
1226894f640SThomas Richard 	u8 status;
1236894f640SThomas Richard 	int ret;
1246894f640SThomas Richard 
1256894f640SThomas Richard 	ret = cgbc_command(cgbc, &cmd, sizeof(cmd), NULL, 0, &status);
1266894f640SThomas Richard 	if (ret)
1276894f640SThomas Richard 		return ret;
1286894f640SThomas Richard 
1296894f640SThomas Richard 	return status;
1306894f640SThomas Richard }
1316894f640SThomas Richard 
cgbc_i2c_set_frequency(struct i2c_adapter * adap,unsigned int bus_frequency)1326894f640SThomas Richard static int cgbc_i2c_set_frequency(struct i2c_adapter *adap,
1336894f640SThomas Richard 				  unsigned int bus_frequency)
1346894f640SThomas Richard {
1356894f640SThomas Richard 	struct i2c_algo_cgbc_data *algo_data = adap->algo_data;
1366894f640SThomas Richard 	struct cgbc_i2c_data *i2c = i2c_get_adapdata(adap);
1376894f640SThomas Richard 	struct cgbc_device_data *cgbc = i2c->cgbc;
1386894f640SThomas Richard 	u8 cmd[2], data;
1396894f640SThomas Richard 	int ret;
1406894f640SThomas Richard 
1416894f640SThomas Richard 	if (bus_frequency > CGBC_I2C_FREQ_MAX_HZ ||
1426894f640SThomas Richard 	    bus_frequency < CGBC_I2C_FREQ_MIN_HZ) {
1436894f640SThomas Richard 		dev_info(i2c->dev, "invalid frequency %u, using default\n", bus_frequency);
1446894f640SThomas Richard 		bus_frequency = I2C_MAX_STANDARD_MODE_FREQ;
1456894f640SThomas Richard 	}
1466894f640SThomas Richard 
1476894f640SThomas Richard 	cmd[0] = CGBC_I2C_CMD_SPEED | algo_data->bus_id;
1486894f640SThomas Richard 	cmd[1] = cgbc_i2c_freq_to_reg(bus_frequency);
1496894f640SThomas Richard 
1506894f640SThomas Richard 	ret = cgbc_command(cgbc, &cmd, sizeof(cmd), &data, 1, NULL);
1516894f640SThomas Richard 	if (ret)
1526894f640SThomas Richard 		return dev_err_probe(i2c->dev, ret,
1536894f640SThomas Richard 				     "Failed to initialize I2C bus %s",
1546894f640SThomas Richard 				     adap->name);
1556894f640SThomas Richard 
1566894f640SThomas Richard 	cmd[1] = 0x00;
1576894f640SThomas Richard 
1586894f640SThomas Richard 	ret = cgbc_command(cgbc, &cmd, sizeof(cmd), &data, 1, NULL);
1596894f640SThomas Richard 	if (ret)
1606894f640SThomas Richard 		return dev_err_probe(i2c->dev, ret,
1616894f640SThomas Richard 				     "Failed to get I2C bus frequency");
1626894f640SThomas Richard 
1636894f640SThomas Richard 	bus_frequency = cgbc_i2c_reg_to_freq(data);
1646894f640SThomas Richard 
1656894f640SThomas Richard 	dev_dbg(i2c->dev, "%s is running at %d Hz\n", adap->name, bus_frequency);
1666894f640SThomas Richard 
1676894f640SThomas Richard 	/*
1686894f640SThomas Richard 	 * The read_maxtime_us variable represents the maximum time to wait
1696894f640SThomas Richard 	 * for data during a read operation. The maximum amount of data that
1706894f640SThomas Richard 	 * can be read by a command is CGBC_I2C_READ_MAX_LEN.
1716894f640SThomas Richard 	 * Therefore, calculate the max time to properly size the timeout.
1726894f640SThomas Richard 	 */
1736894f640SThomas Richard 	algo_data->read_maxtime_us = (BITS_PER_BYTE + 1) * CGBC_I2C_READ_MAX_LEN
1746894f640SThomas Richard 		* USEC_PER_SEC / bus_frequency;
1756894f640SThomas Richard 
1766894f640SThomas Richard 	return 0;
1776894f640SThomas Richard }
1786894f640SThomas Richard 
cgbc_i2c_xfer_to_cmd(struct cgbc_i2c_transfer xfer,u8 * cmd)1796894f640SThomas Richard static unsigned int cgbc_i2c_xfer_to_cmd(struct cgbc_i2c_transfer xfer, u8 *cmd)
1806894f640SThomas Richard {
1816894f640SThomas Richard 	int i = 0;
1826894f640SThomas Richard 
1836894f640SThomas Richard 	cmd[i++] = CGBC_I2C_CMD_START | xfer.bus_id;
1846894f640SThomas Richard 
1856894f640SThomas Richard 	cmd[i] = (xfer.start) ? CGBC_I2C_START : 0x00;
1866894f640SThomas Richard 	if (xfer.stop)
1876894f640SThomas Richard 		cmd[i] |= CGBC_I2C_STOP;
1886894f640SThomas Richard 	cmd[i++] |= (xfer.start) ? xfer.write + 1 : xfer.write;
1896894f640SThomas Richard 
1906894f640SThomas Richard 	cmd[i++] = (xfer.last_ack) ? (xfer.read | CGBC_I2C_LAST_ACK) : xfer.read;
1916894f640SThomas Richard 
1926894f640SThomas Richard 	if (xfer.start)
1936894f640SThomas Richard 		cmd[i++] = xfer.addr;
1946894f640SThomas Richard 
1956894f640SThomas Richard 	if (xfer.write > 0)
1966894f640SThomas Richard 		memcpy(&cmd[i], &xfer.data, xfer.write);
1976894f640SThomas Richard 
1986894f640SThomas Richard 	return i + xfer.write;
1996894f640SThomas Richard }
2006894f640SThomas Richard 
cgbc_i2c_xfer_msg(struct i2c_adapter * adap)2016894f640SThomas Richard static int cgbc_i2c_xfer_msg(struct i2c_adapter *adap)
2026894f640SThomas Richard {
2036894f640SThomas Richard 	struct i2c_algo_cgbc_data *algo_data = adap->algo_data;
2046894f640SThomas Richard 	struct cgbc_i2c_data *i2c = i2c_get_adapdata(adap);
2056894f640SThomas Richard 	struct cgbc_device_data *cgbc = i2c->cgbc;
2066894f640SThomas Richard 	struct i2c_msg *msg = i2c->msg;
2076894f640SThomas Richard 	u8 cmd[CGBC_I2C_CMD_SIZE];
2086894f640SThomas Richard 	int ret, max_len, len, i;
2096894f640SThomas Richard 	unsigned int cmd_len;
2106894f640SThomas Richard 	u8 cmd_data;
2116894f640SThomas Richard 
2126894f640SThomas Richard 	struct cgbc_i2c_transfer xfer = {
2136894f640SThomas Richard 		.bus_id = algo_data->bus_id,
2146894f640SThomas Richard 		.addr = i2c_8bit_addr_from_msg(msg),
2156894f640SThomas Richard 	};
2166894f640SThomas Richard 
2176894f640SThomas Richard 	if (i2c->state == CGBC_I2C_STATE_DONE)
2186894f640SThomas Richard 		return 0;
2196894f640SThomas Richard 
2206894f640SThomas Richard 	ret = cgbc_i2c_get_status(adap);
2216894f640SThomas Richard 
2226894f640SThomas Richard 	if (ret == CGBC_I2C_STAT_BUSY)
2236894f640SThomas Richard 		return -EBUSY;
2246894f640SThomas Richard 	else if (ret < 0)
2256894f640SThomas Richard 		goto err;
2266894f640SThomas Richard 
2276894f640SThomas Richard 	if (i2c->state == CGBC_I2C_STATE_INIT ||
2286894f640SThomas Richard 	    (i2c->state == CGBC_I2C_STATE_WRITE && msg->flags & I2C_M_RD))
2296894f640SThomas Richard 		xfer.start = true;
2306894f640SThomas Richard 
2316894f640SThomas Richard 	i2c->state = (msg->flags & I2C_M_RD) ? CGBC_I2C_STATE_READ : CGBC_I2C_STATE_WRITE;
2326894f640SThomas Richard 
2336894f640SThomas Richard 	max_len = (i2c->state == CGBC_I2C_STATE_READ) ?
2346894f640SThomas Richard 		CGBC_I2C_READ_MAX_LEN : CGBC_I2C_WRITE_MAX_LEN;
2356894f640SThomas Richard 
2366894f640SThomas Richard 	if (msg->len - i2c->pos > max_len) {
2376894f640SThomas Richard 		len = max_len;
2386894f640SThomas Richard 	} else {
2396894f640SThomas Richard 		len = msg->len - i2c->pos;
2406894f640SThomas Richard 
2416894f640SThomas Richard 		if (i2c->nmsgs == 1)
2426894f640SThomas Richard 			xfer.stop = true;
2436894f640SThomas Richard 	}
2446894f640SThomas Richard 
2456894f640SThomas Richard 	if (i2c->state == CGBC_I2C_STATE_WRITE) {
2466894f640SThomas Richard 		xfer.write = len;
2476894f640SThomas Richard 		xfer.read = 0;
2486894f640SThomas Richard 
2496894f640SThomas Richard 		for (i = 0; i < len; i++)
2506894f640SThomas Richard 			xfer.data[i] = msg->buf[i2c->pos + i];
2516894f640SThomas Richard 
2526894f640SThomas Richard 		cmd_len = cgbc_i2c_xfer_to_cmd(xfer, &cmd[0]);
2536894f640SThomas Richard 
2546894f640SThomas Richard 		ret = cgbc_command(cgbc, &cmd, cmd_len, NULL, 0, NULL);
2556894f640SThomas Richard 		if (ret)
2566894f640SThomas Richard 			goto err;
2576894f640SThomas Richard 	} else if (i2c->state == CGBC_I2C_STATE_READ) {
2586894f640SThomas Richard 		xfer.write = 0;
2596894f640SThomas Richard 		xfer.read = len;
2606894f640SThomas Richard 
2616894f640SThomas Richard 		if (i2c->nmsgs > 1 || msg->len - i2c->pos > max_len)
2626894f640SThomas Richard 			xfer.read |= CGBC_I2C_LAST_ACK;
2636894f640SThomas Richard 
2646894f640SThomas Richard 		cmd_len = cgbc_i2c_xfer_to_cmd(xfer, &cmd[0]);
2656894f640SThomas Richard 		ret = cgbc_command(cgbc, &cmd, cmd_len, NULL, 0, NULL);
2666894f640SThomas Richard 		if (ret)
2676894f640SThomas Richard 			goto err;
2686894f640SThomas Richard 
2696894f640SThomas Richard 		ret = read_poll_timeout(cgbc_i2c_get_status, ret,
2706894f640SThomas Richard 					ret != CGBC_I2C_STAT_BUSY, 0,
2716894f640SThomas Richard 					2 * algo_data->read_maxtime_us, false, adap);
2726894f640SThomas Richard 		if (ret < 0)
2736894f640SThomas Richard 			goto err;
2746894f640SThomas Richard 
2756894f640SThomas Richard 		cmd_data = CGBC_I2C_CMD_DATA | algo_data->bus_id;
2766894f640SThomas Richard 		ret = cgbc_command(cgbc, &cmd_data, sizeof(cmd_data),
2776894f640SThomas Richard 				   msg->buf + i2c->pos, len, NULL);
2786894f640SThomas Richard 		if (ret)
2796894f640SThomas Richard 			goto err;
2806894f640SThomas Richard 	}
2816894f640SThomas Richard 
2826894f640SThomas Richard 	if (len == (msg->len - i2c->pos)) {
2836894f640SThomas Richard 		i2c->msg++;
2846894f640SThomas Richard 		i2c->nmsgs--;
2856894f640SThomas Richard 		i2c->pos = 0;
2866894f640SThomas Richard 	} else {
2876894f640SThomas Richard 		i2c->pos += len;
2886894f640SThomas Richard 	}
2896894f640SThomas Richard 
2906894f640SThomas Richard 	if (i2c->nmsgs == 0)
2916894f640SThomas Richard 		i2c->state = CGBC_I2C_STATE_DONE;
2926894f640SThomas Richard 
2936894f640SThomas Richard 	return 0;
2946894f640SThomas Richard 
2956894f640SThomas Richard err:
2966894f640SThomas Richard 	i2c->state = CGBC_I2C_STATE_ERROR;
2976894f640SThomas Richard 	return ret;
2986894f640SThomas Richard }
2996894f640SThomas Richard 
cgbc_i2c_xfer(struct i2c_adapter * adap,struct i2c_msg * msgs,int num)3006894f640SThomas Richard static int cgbc_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
3016894f640SThomas Richard 			 int num)
3026894f640SThomas Richard {
3036894f640SThomas Richard 	struct cgbc_i2c_data *i2c = i2c_get_adapdata(adap);
3046894f640SThomas Richard 	unsigned long timeout = jiffies + HZ;
3056894f640SThomas Richard 	int ret;
3066894f640SThomas Richard 
3076894f640SThomas Richard 	i2c->state = CGBC_I2C_STATE_INIT;
3086894f640SThomas Richard 	i2c->msg = msgs;
3096894f640SThomas Richard 	i2c->nmsgs = num;
3106894f640SThomas Richard 	i2c->pos = 0;
3116894f640SThomas Richard 
3126894f640SThomas Richard 	while (time_before(jiffies, timeout)) {
3136894f640SThomas Richard 		ret = cgbc_i2c_xfer_msg(adap);
3146894f640SThomas Richard 		if (i2c->state == CGBC_I2C_STATE_DONE)
3156894f640SThomas Richard 			return num;
3166894f640SThomas Richard 
3176894f640SThomas Richard 		if (i2c->state == CGBC_I2C_STATE_ERROR)
3186894f640SThomas Richard 			return ret;
3196894f640SThomas Richard 
3206894f640SThomas Richard 		if (ret == 0)
3216894f640SThomas Richard 			timeout = jiffies + HZ;
3226894f640SThomas Richard 	}
3236894f640SThomas Richard 
3246894f640SThomas Richard 	i2c->state = CGBC_I2C_STATE_ERROR;
3256894f640SThomas Richard 	return -ETIMEDOUT;
3266894f640SThomas Richard }
3276894f640SThomas Richard 
cgbc_i2c_func(struct i2c_adapter * adap)3286894f640SThomas Richard static u32 cgbc_i2c_func(struct i2c_adapter *adap)
3296894f640SThomas Richard {
3306894f640SThomas Richard 	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~(I2C_FUNC_SMBUS_QUICK));
3316894f640SThomas Richard }
3326894f640SThomas Richard 
3336894f640SThomas Richard static const struct i2c_algorithm cgbc_i2c_algorithm = {
3346894f640SThomas Richard 	.master_xfer	= cgbc_i2c_xfer,
3356894f640SThomas Richard 	.functionality	= cgbc_i2c_func,
3366894f640SThomas Richard };
3376894f640SThomas Richard 
3386894f640SThomas Richard static struct i2c_algo_cgbc_data cgbc_i2c_algo_data[] = {
3396894f640SThomas Richard 	{ .bus_id = CGBC_I2C_PRIMARY_BUS_ID },
3406894f640SThomas Richard 	{ .bus_id = CGBC_I2C_PM_BUS_ID },
3416894f640SThomas Richard };
3426894f640SThomas Richard 
3436894f640SThomas Richard static const struct i2c_adapter cgbc_i2c_adapter[] = {
3446894f640SThomas Richard 	{
3456894f640SThomas Richard 		.owner		= THIS_MODULE,
3466894f640SThomas Richard 		.name		= "Congatec General Purpose I2C adapter",
3476894f640SThomas Richard 		.class		= I2C_CLASS_DEPRECATED,
3486894f640SThomas Richard 		.algo		= &cgbc_i2c_algorithm,
3496894f640SThomas Richard 		.algo_data	= &cgbc_i2c_algo_data[0],
3506894f640SThomas Richard 		.nr		= -1,
3516894f640SThomas Richard 	},
3526894f640SThomas Richard 	{
3536894f640SThomas Richard 		.owner		= THIS_MODULE,
3546894f640SThomas Richard 		.name		= "Congatec Power Management I2C adapter",
3556894f640SThomas Richard 		.class		= I2C_CLASS_DEPRECATED,
3566894f640SThomas Richard 		.algo		= &cgbc_i2c_algorithm,
3576894f640SThomas Richard 		.algo_data	= &cgbc_i2c_algo_data[1],
3586894f640SThomas Richard 		.nr		= -1,
3596894f640SThomas Richard 	},
3606894f640SThomas Richard };
3616894f640SThomas Richard 
cgbc_i2c_probe(struct platform_device * pdev)3626894f640SThomas Richard static int cgbc_i2c_probe(struct platform_device *pdev)
3636894f640SThomas Richard {
3646894f640SThomas Richard 	struct cgbc_device_data *cgbc = dev_get_drvdata(pdev->dev.parent);
3656894f640SThomas Richard 	struct cgbc_i2c_data *i2c;
3666894f640SThomas Richard 	int ret;
3676894f640SThomas Richard 
3686894f640SThomas Richard 	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
3696894f640SThomas Richard 	if (!i2c)
3706894f640SThomas Richard 		return -ENOMEM;
3716894f640SThomas Richard 
3726894f640SThomas Richard 	i2c->cgbc = cgbc;
3736894f640SThomas Richard 	i2c->dev = &pdev->dev;
3746894f640SThomas Richard 	i2c->adap = cgbc_i2c_adapter[pdev->id];
3756894f640SThomas Richard 	i2c->adap.dev.parent = i2c->dev;
3766894f640SThomas Richard 	i2c_set_adapdata(&i2c->adap, i2c);
3776894f640SThomas Richard 	platform_set_drvdata(pdev, i2c);
3786894f640SThomas Richard 
3796894f640SThomas Richard 	ret = cgbc_i2c_set_frequency(&i2c->adap, I2C_MAX_STANDARD_MODE_FREQ);
3806894f640SThomas Richard 	if (ret)
3816894f640SThomas Richard 		return ret;
3826894f640SThomas Richard 
3836894f640SThomas Richard 	return i2c_add_numbered_adapter(&i2c->adap);
3846894f640SThomas Richard }
3856894f640SThomas Richard 
cgbc_i2c_remove(struct platform_device * pdev)3866894f640SThomas Richard static void cgbc_i2c_remove(struct platform_device *pdev)
3876894f640SThomas Richard {
3886894f640SThomas Richard 	struct cgbc_i2c_data *i2c = platform_get_drvdata(pdev);
3896894f640SThomas Richard 
3906894f640SThomas Richard 	i2c_del_adapter(&i2c->adap);
3916894f640SThomas Richard }
3926894f640SThomas Richard 
3936894f640SThomas Richard static struct platform_driver cgbc_i2c_driver = {
3946894f640SThomas Richard 	.driver = {
3956894f640SThomas Richard 		.name = "cgbc-i2c",
3966894f640SThomas Richard 	},
3976894f640SThomas Richard 	.probe		= cgbc_i2c_probe,
398*e70140baSLinus Torvalds 	.remove		= cgbc_i2c_remove,
3996894f640SThomas Richard };
4006894f640SThomas Richard 
4016894f640SThomas Richard module_platform_driver(cgbc_i2c_driver);
4026894f640SThomas Richard 
4036894f640SThomas Richard MODULE_DESCRIPTION("Congatec Board Controller I2C Driver");
4046894f640SThomas Richard MODULE_AUTHOR("Thomas Richard <thomas.richard@bootlin.com>");
4056894f640SThomas Richard MODULE_LICENSE("GPL");
4066894f640SThomas Richard MODULE_ALIAS("platform:cgbc_i2c");
407