X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fi2c%2Fmvtwsi.c;h=14c594d648ba24ee8f6b1d22db4588450432b88f;hb=5a1a8a63be8f7262a300eddafb18020926b12fb6;hp=dfbc4e053f56683fae878fc5b7ba627480a60ef6;hpb=821560fd8e43eecc208c1c52ad24faadb6b52703;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index dfbc4e0..14c594d 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -1,17 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for the TWSI (i2c) controller found on the Marvell * orion5x and kirkwood SoC families. * * Author: Albert Aribaud * Copyright (c) 2010 Albert Aribaud. - * - * SPDX-License-Identifier: GPL-2.0+ */ #include #include +#include +#include #include #include +#include #include #ifdef CONFIG_DM_I2C #include @@ -25,9 +27,9 @@ DECLARE_GLOBAL_DATA_PTR; */ #ifndef CONFIG_DM_I2C -#if defined(CONFIG_ORION5X) +#if defined(CONFIG_ARCH_ORION5X) #include -#elif (defined(CONFIG_KIRKWOOD) || defined(CONFIG_ARCH_MVEBU)) +#elif (defined(CONFIG_ARCH_KIRKWOOD) || defined(CONFIG_ARCH_MVEBU)) #include #elif defined(CONFIG_ARCH_SUNXI) #include @@ -58,6 +60,7 @@ struct mvtwsi_registers { u32 status; u32 baudrate; u32 soft_reset; + u32 debug; /* Dummy field for build compatibility with mvebu */ }; #else @@ -71,8 +74,10 @@ struct mvtwsi_registers { u32 baudrate; /* When writing */ }; u32 xtnd_slave_addr; - u32 reserved[2]; + u32 reserved0[2]; u32 soft_reset; + u32 reserved1[27]; + u32 debug; }; #endif @@ -268,6 +273,17 @@ static int twsi_wait(struct mvtwsi_registers *twsi, int expected_status, do { control = readl(&twsi->control); if (control & MVTWSI_CONTROL_IFLG) { + /* + * On Armada 38x it seems that the controller works as + * if it first set the MVTWSI_CONTROL_IFLAG in the + * control register and only after that it changed the + * status register. + * This sometimes caused weird bugs which only appeared + * on selected I2C speeds and even then only sometimes. + * We therefore add here a simple ndealy(100), which + * seems to fix this weird bug. + */ + ndelay(100); status = readl(&twsi->status); if (status == expected_status) return 0; @@ -487,10 +503,14 @@ static uint __twsi_i2c_set_bus_speed(struct mvtwsi_registers *twsi, static void __twsi_i2c_init(struct mvtwsi_registers *twsi, int speed, int slaveadd, uint *actual_speed) { + uint tmp_speed; + /* Reset controller */ twsi_reset(twsi); /* Set speed */ - *actual_speed = __twsi_i2c_set_bus_speed(twsi, speed); + tmp_speed = __twsi_i2c_set_bus_speed(twsi, speed); + if (actual_speed) + *actual_speed = tmp_speed; /* Set slave address; even though we don't use it */ writel(slaveadd, &twsi->slave_address); writel(0, &twsi->xtnd_slave_addr); @@ -778,7 +798,7 @@ static int mvtwsi_i2c_ofdata_to_platdata(struct udevice *bus) { struct mvtwsi_i2c_dev *dev = dev_get_priv(bus); - dev->base = devfdt_get_addr_ptr(bus); + dev->base = dev_read_addr_ptr(bus); if (!dev->base) return -ENOMEM; @@ -787,8 +807,27 @@ static int mvtwsi_i2c_ofdata_to_platdata(struct udevice *bus) "cell-index", -1); dev->slaveadd = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus), "u-boot,i2c-slave-addr", 0x0); - dev->speed = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus), - "clock-frequency", 100000); + dev->speed = dev_read_u32_default(bus, "clock-frequency", + I2C_SPEED_STANDARD_RATE); + + return 0; +} + +static void twsi_disable_i2c_slave(struct mvtwsi_registers *twsi) +{ + clrbits_le32(&twsi->debug, BIT(18)); +} + +static int mvtwsi_i2c_bind(struct udevice *bus) +{ + struct mvtwsi_registers *twsi = dev_read_addr_ptr(bus); + + /* Disable the hidden slave in i2c0 of these platforms */ + if ((IS_ENABLED(CONFIG_ARMADA_38X) || IS_ENABLED(CONFIG_ARCH_KIRKWOOD) + || IS_ENABLED(CONFIG_ARMADA_8K)) + && bus->req_seq == 0) + twsi_disable_i2c_slave(twsi); + return 0; } @@ -847,6 +886,7 @@ U_BOOT_DRIVER(i2c_mvtwsi) = { .name = "i2c_mvtwsi", .id = UCLASS_I2C, .of_match = mvtwsi_i2c_ids, + .bind = mvtwsi_i2c_bind, .probe = mvtwsi_i2c_probe, .ofdata_to_platdata = mvtwsi_i2c_ofdata_to_platdata, .priv_auto_alloc_size = sizeof(struct mvtwsi_i2c_dev),