Skip to content

Commit 66b0c28

Browse files
vadimp-nvidiawsakernel
authored andcommitted
i2c: mlxcpld: Add support for I2C bus frequency setting
Add support for I2C bus frequency setting according to the specific system capability. This capability is obtained from CPLD frequency setting register, which could be provided through the platform data. If such register is provided, it specifies minimal I2C bus frequency to be used for the devices attached to the I2C bus. Supported freqeuncies are 100KHz, 400KHz, 1MHz, while 100KHz is the default. Signed-off-by: Vadim Pasternak <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 45c6c87 commit 66b0c28

File tree

1 file changed

+62
-1
lines changed

1 file changed

+62
-1
lines changed

drivers/i2c/busses/i2c-mlxcpld.c

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
#include <linux/io.h>
1212
#include <linux/kernel.h>
1313
#include <linux/module.h>
14+
#include <linux/platform_data/mlxreg.h>
1415
#include <linux/platform_device.h>
16+
#include <linux/regmap.h>
1517

1618
/* General defines */
1719
#define MLXPLAT_CPLD_LPC_I2C_BASE_ADDR 0x2000
@@ -46,6 +48,16 @@
4648
#define MLXCPLD_LPCI2C_ACK_IND 1
4749
#define MLXCPLD_LPCI2C_NACK_IND 2
4850

51+
#define MLXCPLD_I2C_FREQ_1000KHZ_SET 0x04
52+
#define MLXCPLD_I2C_FREQ_400KHZ_SET 0x0f
53+
#define MLXCPLD_I2C_FREQ_100KHZ_SET 0x42
54+
55+
enum mlxcpld_i2c_frequency {
56+
MLXCPLD_I2C_FREQ_1000KHZ = 1,
57+
MLXCPLD_I2C_FREQ_400KHZ = 2,
58+
MLXCPLD_I2C_FREQ_100KHZ = 3,
59+
};
60+
4961
struct mlxcpld_i2c_curr_xfer {
5062
u8 cmd;
5163
u8 addr_width;
@@ -463,8 +475,45 @@ static struct i2c_adapter mlxcpld_i2c_adapter = {
463475
.nr = MLXCPLD_I2C_BUS_NUM,
464476
};
465477

478+
static int
479+
mlxcpld_i2c_set_frequency(struct mlxcpld_i2c_priv *priv,
480+
struct mlxreg_core_hotplug_platform_data *pdata)
481+
{
482+
struct mlxreg_core_item *item = pdata->items;
483+
struct mlxreg_core_data *data;
484+
u32 regval;
485+
u8 freq;
486+
int err;
487+
488+
if (!item)
489+
return 0;
490+
491+
/* Read frequency setting. */
492+
data = item->data;
493+
err = regmap_read(pdata->regmap, data->reg, &regval);
494+
if (err)
495+
return err;
496+
497+
/* Set frequency only if it is not 100KHz, which is default. */
498+
switch ((data->reg & data->mask) >> data->bit) {
499+
case MLXCPLD_I2C_FREQ_1000KHZ:
500+
freq = MLXCPLD_I2C_FREQ_1000KHZ_SET;
501+
break;
502+
case MLXCPLD_I2C_FREQ_400KHZ:
503+
freq = MLXCPLD_I2C_FREQ_400KHZ_SET;
504+
break;
505+
default:
506+
return 0;
507+
}
508+
509+
mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_HALF_CYC_REG, &freq, 1);
510+
511+
return 0;
512+
}
513+
466514
static int mlxcpld_i2c_probe(struct platform_device *pdev)
467515
{
516+
struct mlxreg_core_hotplug_platform_data *pdata;
468517
struct mlxcpld_i2c_priv *priv;
469518
int err;
470519
u8 val;
@@ -479,6 +528,14 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
479528
priv->dev = &pdev->dev;
480529
priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
481530

531+
/* Set I2C bus frequency if platform data provides this info. */
532+
pdata = dev_get_platdata(&pdev->dev);
533+
if (pdata) {
534+
err = mlxcpld_i2c_set_frequency(priv, pdata);
535+
if (err)
536+
goto mlxcpld_i2_probe_failed;
537+
}
538+
482539
/* Register with i2c layer */
483540
mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
484541
/* Read capability register */
@@ -497,8 +554,12 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
497554

498555
err = i2c_add_numbered_adapter(&priv->adap);
499556
if (err)
500-
mutex_destroy(&priv->lock);
557+
goto mlxcpld_i2_probe_failed;
501558

559+
return 0;
560+
561+
mlxcpld_i2_probe_failed:
562+
mutex_destroy(&priv->lock);
502563
return err;
503564
}
504565

0 commit comments

Comments
 (0)