[i2c] [PATCH 8/12] drivers: PMC MSP71xx TWI driver

Trilok Soni soni.trilok at gmail.com
Fri Jun 29 11:22:57 CEST 2007


On 6/29/07, Marc St-Jean <stjeanma at pmc-sierra.com> wrote:
> [PATCH 8/12] drivers: PMC MSP71xx TWI driver
>
> Patch to add TWI driver for the PMC-Sierra MSP71xx devices.
>
> Thanks,
> Marc
>
> Signed-off-by: Marc St-Jean <Marc_St-Jean at pmc-sierra.com>
> ---
> Changes since last post:
> - Changed config item to no longer depend on I2C and updated help text.
> - Converted to platform device driver and rewrote probe/remove functions.
> - Changed xfer_command to fix up be64 handling in .
> - Changed master_xfer function to eliminate support for multiple commands
> other that simple write-read. Fixed probing workaround to not perform a read.
> - Updated IRQ flags.
> - Returned more meaningful error codes.
> - Removed unnecessary headers and definitions.
> - Removed get_clock_config function as not currently used.
> - Removed algo_data function pointers and made direct calls.
> - Removed extra casts and backets.
> - Removed redundant debugging output.
> - Other cleanups as requested by feedback.
>
>  Kconfig      |    6
>  Makefile     |    1
>  i2c-pmcmsp.c |  674 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 681 insertions(+)
>
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index ece31d2..303faf9 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -582,4 +582,10 @@ config I2C_PNX
>           This driver can also be built as a module.  If so, the module
>           will be called i2c-pnx.
>
> +config I2C_PMCMSP
> +       tristate "PMC MSP I2C TWI Controller"
> +       depends on PMC_MSP
> +       help
> +         This driver supports the PMC TWI controller on MSP devices.

Better if you add one line like "This driver can also be built as
module, If so, the module
will be called i2c-pmcmsp." :)

> +
>  endmenu

...

> +
> +/*
> + * Sends an i2c command out on the adapter
> + */
> +static int pmcmsptwi_master_xfer(struct i2c_adapter *adap,
> +                               struct i2c_msg *msg, int num)
> +{
> +       struct pmcmsptwi_data *data = adap->algo_data;

i2c_get_adapdata?

> +       struct pmcmsptwi_cmd cmd;
> +       struct pmcmsptwi_cfg oldcfg, newcfg;
> +       bool probe = false;
> +       u8 probe_buf[] = { 0 };
> +       int ret;
> +
> +       if (num > 2) {
> +               dev_dbg(&adap->dev, "%d messages unsupported\n", num);
> +               return -EINVAL;
> +       } else if (num == 2) {
> +               /* Check for a dual write-then-read command */
> +               struct i2c_msg *nextmsg = msg + 1;
> +               if (!(msg->flags & I2C_M_RD) &&
> +                   (nextmsg->flags & I2C_M_RD) &&
> +                   msg->addr == nextmsg->addr) {
> +                       cmd.type = MSP_TWI_CMD_WRITE_READ;
> +                       cmd.write_len = msg->len;
> +                       cmd.write_data = msg->buf;
> +                       cmd.read_len = nextmsg->len;
> +                       cmd.read_data = nextmsg->buf;
> +               } else {
> +                       dev_dbg(&adap->dev,
> +                               "Non write-read dual messages unsupported\n");
> +                       return -EINVAL;
> +               }
> +       } else if (msg->flags & I2C_M_RD) {
> +               cmd.type = MSP_TWI_CMD_READ;
> +               cmd.read_len = msg->len;
> +               cmd.read_data = msg->buf;
> +               cmd.write_len = 0;
> +               cmd.write_data = NULL;
> +       } else {
> +               cmd.type = MSP_TWI_CMD_WRITE;
> +               cmd.read_len = 0;
> +               cmd.read_data = NULL;
> +               cmd.write_len = msg->len;
> +               cmd.write_data = msg->buf;
> +       }
> +
> +       if (msg->len == 0) {
> +               if (msg->flags & I2C_M_RD) {
> +                       dev_dbg(&adap->dev,
> +                               "Read of 0 bytes unsupported\n");
> +                       return -EINVAL;
> +               } else {
> +                       dev_dbg(&adap->dev, "Probing for slave at 0x%02x\n",
> +                               msg->addr & 0xff);
> +                       probe = true;
> +
> +                       /* Probe is a special write of 1 byte */
> +                       cmd.write_len = 1;
> +                       cmd.write_data = probe_buf;
> +               }
> +       }
> +
> +       cmd.addr = msg->addr;
> +
> +       if (probe || (msg->flags & I2C_M_TEN)) {
> +               pmcmsptwi_get_twi_config(&newcfg, data);
> +               memcpy(&oldcfg, &newcfg, sizeof(oldcfg));
> +
> +               /* For probes, we don't want any retries */
> +               if (probe)
> +                       newcfg.nak = 0;
> +
> +               /* Set the special 10-bit address flag, if required */
> +               if (msg->flags & I2C_M_TEN)
> +                       newcfg.add10 = 1;
> +
> +               pmcmsptwi_set_twi_config(&newcfg, data);
> +       }
> +
> +       /* Execute the command */
> +       ret = pmcmsptwi_xfer_cmd(&cmd, data);
> +
> +       if (probe || (msg->flags & I2C_M_TEN))
> +               pmcmsptwi_set_twi_config(&oldcfg, data);
> +
> +       dev_dbg(&adap->dev, "I2C %s of %d bytes ",
> +               (msg->flags & I2C_M_RD) ? "read" : "write", msg->len);
> +       if (ret != MSP_TWI_XFER_OK) {
> +               /*
> +                * TODO: We could potentially loop and retry in the case
> +                * of MSP_TWI_XFER_TIMEOUT.
> +                */
> +               dev_dbg(&adap->dev, "failed\n");
> +               return -1;
> +       }
> +
> +       dev_dbg(&adap->dev, "succeeded\n");
> +       return 0;
> +}
> +
> +static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter)
> +{
> +       return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL;
> +}
> +
> +/* -- Initialization -- */
> +
> +static struct i2c_algorithm pmcmsptwi_algo = {
> +       .master_xfer    = pmcmsptwi_master_xfer,
> +       .functionality  = pmcmsptwi_i2c_func,
> +};
> +
> +static struct i2c_adapter pmcmsptwi_adapter = {
> +       .owner          = THIS_MODULE,
> +       .class          = I2C_CLASS_HWMON,
> +       .algo           = &pmcmsptwi_algo,
> +       .algo_data      = &pmcmsptwi_data,
> +       .name           = DRV_NAME,
> +};
> +
> +static struct platform_driver pmcmsptwi_driver = {
> +       .probe  = pmcmsptwi_probe,
> +       .remove = __devexit_p(pmcmsptwi_remove),
> +       .driver {
> +               .name = DRV_NAME,
> +               .owner  = THIS_MODULE,
> +       },
> +};
> +
> +static int __init pmcmsptwi_init(void)
> +{
> +       printk(KERN_INFO "PMC MSP TWI Driver\n");
> +
> +       if (platform_driver_register(&pmcmsptwi_driver)) {
> +               printk(KERN_ERR "Driver registration failed\n");
> +               return -ENOMEM;

Return code should be -ENODEV not -ENOMEM.

> +       }
> +
> +       return 0;
> +}
> +
> +static void __exit pmcmsptwi_exit(void)
> +{
> +       platform_driver_unregister(&pmcmsptwi_driver);
> +}
> +
> +MODULE_DESCRIPTION("PMC MSP TWI/SMBus/I2C driver");
> +MODULE_LICENSE("GPL");
> +
> +module_init(pmcmsptwi_init);
> +module_exit(pmcmsptwi_exit);
>
> _______________________________________________
> i2c mailing list
> i2c at lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/i2c
>


-- 
--Trilok Soni



More information about the i2c mailing list