--- zzzz-none-000/linux-3.10.107/drivers/i2c/busses/i2c-cpm.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/i2c/busses/i2c-cpm.c 2021-02-04 17:41:59.000000000 +0000 @@ -23,26 +23,22 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include -#include #include #include #include #include #include #include +#include #include +#include #include -#include #include #include @@ -312,22 +308,12 @@ struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg; struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram; struct i2c_msg *pmsg; - int ret, i; + int ret; int tptr; int rptr; cbd_t __iomem *tbdf; cbd_t __iomem *rbdf; - if (num > CPM_MAXBD) - return -EINVAL; - - /* Check if we have any oversized READ requests */ - for (i = 0; i < num; i++) { - pmsg = &msgs[i]; - if (pmsg->len >= CPM_MAX_READ) - return -EINVAL; - } - /* Reset to use first buffer */ out_be16(&i2c_ram->rbptr, in_be16(&i2c_ram->rbase)); out_be16(&i2c_ram->tbptr, in_be16(&i2c_ram->tbase)); @@ -338,6 +324,14 @@ tptr = 0; rptr = 0; + /* + * If there was a collision in the last i2c transaction, + * Set I2COM_MASTER as it was cleared during collision. + */ + if (in_be16(&tbdf->cbd_sc) & BD_SC_CL) { + out_8(&cpm->i2c_reg->i2com, I2COM_MASTER); + } + while (tptr < num) { pmsg = &msgs[tptr]; dev_dbg(&adap->dev, "R: %d T: %d\n", rptr, tptr); @@ -420,10 +414,18 @@ .functionality = cpm_i2c_func, }; +/* CPM_MAX_READ is also limiting writes according to the code! */ +static struct i2c_adapter_quirks cpm_i2c_quirks = { + .max_num_msgs = CPM_MAXBD, + .max_read_len = CPM_MAX_READ, + .max_write_len = CPM_MAX_READ, +}; + static const struct i2c_adapter cpm_ops = { .owner = THIS_MODULE, .name = "i2c-cpm", .algo = &cpm_i2c_algo, + .quirks = &cpm_i2c_quirks, }; static int cpm_i2c_setup(struct cpm_i2c *cpm) @@ -440,7 +442,7 @@ init_waitqueue_head(&cpm->i2c_wait); - cpm->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); + cpm->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0); if (!cpm->irq) return -EINVAL; @@ -646,7 +648,7 @@ cpm->ofdev = ofdev; - dev_set_drvdata(&ofdev->dev, cpm); + platform_set_drvdata(ofdev, cpm); cpm->adap = cpm_ops; i2c_set_adapdata(&cpm->adap, cpm); @@ -673,11 +675,6 @@ dev_dbg(&ofdev->dev, "hw routines for %s registered.\n", cpm->adap.name); - /* - * register OF I2C devices - */ - of_i2c_register_devices(&cpm->adap); - return 0; out_shut: cpm_i2c_shutdown(cpm); @@ -689,7 +686,7 @@ static int cpm_i2c_remove(struct platform_device *ofdev) { - struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev); + struct cpm_i2c *cpm = platform_get_drvdata(ofdev); i2c_del_adapter(&cpm->adap); @@ -717,7 +714,6 @@ .remove = cpm_i2c_remove, .driver = { .name = "fsl-i2c-cpm", - .owner = THIS_MODULE, .of_match_table = cpm_i2c_match, }, };