mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
This cycle, I2C removes the currently unused CLASS_DDC support
(controllers set the flag, but there is no client to use it). Also, CLASS_SPD support gets simplified to prepare removal in the future. Class based instantiation is not recommended these days anyhow. Furthermore, I2C core now creates a debugfs directory per I2C adapter. Current bus driver users were converted to use it. Then, there are also quite some driver updates. Standing out are patches for the wmt-driver which is refactored to support more variants. This is the rebased pull request where a large series for the designware driver was dropped. -----BEGIN PGP SIGNATURE----- iQJDBAABCgAtFiEEOZGx6rniZ1Gk92RdFA3kzBSgKbYFAmWph0UPHHdzYUBrZXJu ZWwub3JnAAoJEBQN5MwUoCm2kbIQAJotSmX0mM+nNPReYCMMiloxoxUwgpiErNwY WDrYQSezthAJ1LDsGOEeLcE4f4I+UcUHBO1BoERtOZg3cGtE0Ii5N845sp100S9O ktyaKS5utoErymThWFFrnZX60/8yKXUMzZmNzy96560gPcxbFyyyVhKfBSPzK9T+ O8CGu7GRNqgWHlvH3yqGeCbreWYrYVSrluEpBu6807cp3zDxrU+autOnsewm5+md ka3DdqrbxJSblYK8fJKESAUgkRmZgYKbgl0iiCuqX+ib6I4OA3Z68ny7dl0fY3Ws vwt7d88SaBKDdJmUZyb/sm4aJsW69GN+ECZolxrn4TIw45k4tes2s6Ma5+TV3E9h Fd1RuqduFEqQ7cj31UPe2x8rgj5Fo5nbjCWxdZv+/3zF8+cHwi8iwkp2PScsPCsa fmCdehUE5DrgobsRNANe6XJzxY5wp2VNpGEWKeaQz2Z0/d9T1YFS7a8aewvhXoPC isZboi6GQh2XoE8UgGJa29VUuaIkUW513DwCGw8mz1yKN+kHGcsRXXjkjaZoQn3U MMvh/zkI2Hpy/m2R8PWeIq5XhLJvmlZ19JJzUHJIjXh9Fn9EVtXhlUleh6mzMfeM n8NOg7Eukep2sBgmaufkUKz2Jtogs59YDSXZEvqJjIkPM2Wi0hA18Qj+pilES1ff 3ckk3mxY =8D3Q -----END PGP SIGNATURE----- Merge tag 'i2c-for-6.8-rc1-rebased' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux Pull i2c updates from Wolfram Sang: "This removes the currently unused CLASS_DDC support (controllers set the flag, but there is no client to use it). Also, CLASS_SPD support gets simplified to prepare removal in the future. Class based instantiation is not recommended these days anyhow. Furthermore, I2C core now creates a debugfs directory per I2C adapter. Current bus driver users were converted to use it. Finally, quite some driver updates. Standing out are patches for the wmt-driver which is refactored to support more variants. This is the rebased pull request where a large series for the designware driver was dropped" * tag 'i2c-for-6.8-rc1-rebased' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (38 commits) MAINTAINERS: use proper email for my I2C work i2c: stm32f7: add support for stm32mp25 soc i2c: stm32f7: perform I2C_ISR read once at beginning of event isr dt-bindings: i2c: document st,stm32mp25-i2c compatible i2c: stm32f7: simplify status messages in case of errors i2c: stm32f7: perform most of irq job in threaded handler i2c: stm32f7: use dev_err_probe upon calls of devm_request_irq i2c: i801: Add lis3lv02d for Dell XPS 15 7590 i2c: i801: Add lis3lv02d for Dell Precision 3540 i2c: wmt: Reduce redundant: REG_CR setting i2c: wmt: Reduce redundant: function parameter i2c: wmt: Reduce redundant: clock mode setting i2c: wmt: Reduce redundant: wait event complete i2c: wmt: Reduce redundant: bus busy check i2c: mux: reg: Remove class-based device auto-detection support i2c: make i2c_bus_type const dt-bindings: at24: add ROHM BR24G04 eeprom: at24: use of_match_ptr() i2c: cpm: Remove linux,i2c-index conversion from be32 i2c: imx: Make SDA actually optional for bus recovering ...
This commit is contained in:
commit
ed8d84530a
@ -123,6 +123,7 @@ properties:
|
||||
- enum:
|
||||
- onnn,cat24c04
|
||||
- onnn,cat24c05
|
||||
- rohm,br24g04
|
||||
- const: atmel,24c04
|
||||
- items:
|
||||
- const: renesas,r1ex24016
|
||||
|
@ -19,6 +19,7 @@ allOf:
|
||||
- st,stm32f7-i2c
|
||||
- st,stm32mp13-i2c
|
||||
- st,stm32mp15-i2c
|
||||
- st,stm32mp25-i2c
|
||||
then:
|
||||
properties:
|
||||
i2c-scl-rising-time-ns:
|
||||
@ -41,6 +42,30 @@ allOf:
|
||||
clock-frequency:
|
||||
enum: [100000, 400000]
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- st,stm32f4-i2c
|
||||
- st,stm32f7-i2c
|
||||
- st,stm32mp13-i2c
|
||||
- st,stm32mp15-i2c
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 2
|
||||
|
||||
interrupt-names:
|
||||
minItems: 2
|
||||
else:
|
||||
properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-names:
|
||||
maxItems: 1
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
@ -48,6 +73,7 @@ properties:
|
||||
- st,stm32f7-i2c
|
||||
- st,stm32mp13-i2c
|
||||
- st,stm32mp15-i2c
|
||||
- st,stm32mp25-i2c
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@ -56,11 +82,13 @@ properties:
|
||||
items:
|
||||
- description: interrupt ID for I2C event
|
||||
- description: interrupt ID for I2C error
|
||||
minItems: 1
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: event
|
||||
- const: error
|
||||
minItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
@ -10061,7 +10061,7 @@ F: Documentation/i2c/busses/i2c-parport.rst
|
||||
F: drivers/i2c/busses/i2c-parport.c
|
||||
|
||||
I2C SUBSYSTEM
|
||||
M: Wolfram Sang <wsa@kernel.org>
|
||||
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
|
||||
L: linux-i2c@vger.kernel.org
|
||||
S: Maintained
|
||||
W: https://i2c.wiki.kernel.org/
|
||||
|
@ -175,7 +175,6 @@ struct amdgpu_i2c_chan *amdgpu_i2c_create(struct drm_device *dev,
|
||||
|
||||
i2c->rec = *rec;
|
||||
i2c->adapter.owner = THIS_MODULE;
|
||||
i2c->adapter.class = I2C_CLASS_DDC;
|
||||
i2c->adapter.dev.parent = dev->dev;
|
||||
i2c->dev = dev;
|
||||
i2c_set_adapdata(&i2c->adapter, i2c);
|
||||
|
@ -7615,7 +7615,6 @@ create_i2c(struct ddc_service *ddc_service,
|
||||
if (!i2c)
|
||||
return NULL;
|
||||
i2c->base.owner = THIS_MODULE;
|
||||
i2c->base.class = I2C_CLASS_DDC;
|
||||
i2c->base.dev.parent = &adev->pdev->dev;
|
||||
i2c->base.algo = &amdgpu_dm_i2c_algo;
|
||||
snprintf(i2c->base.name, sizeof(i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index);
|
||||
|
@ -1530,7 +1530,6 @@ static int aldebaran_i2c_control_init(struct smu_context *smu)
|
||||
smu_i2c->port = 0;
|
||||
mutex_init(&smu_i2c->mutex);
|
||||
control->owner = THIS_MODULE;
|
||||
control->class = I2C_CLASS_SPD;
|
||||
control->dev.parent = &adev->pdev->dev;
|
||||
control->algo = &aldebaran_i2c_algo;
|
||||
snprintf(control->name, sizeof(control->name), "AMDGPU SMU 0");
|
||||
|
@ -2696,7 +2696,6 @@ static int smu_v13_0_0_i2c_control_init(struct smu_context *smu)
|
||||
smu_i2c->port = i;
|
||||
mutex_init(&smu_i2c->mutex);
|
||||
control->owner = THIS_MODULE;
|
||||
control->class = I2C_CLASS_SPD;
|
||||
control->dev.parent = &adev->pdev->dev;
|
||||
control->algo = &smu_v13_0_0_i2c_algo;
|
||||
snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i);
|
||||
|
@ -1936,7 +1936,6 @@ static int smu_v13_0_6_i2c_control_init(struct smu_context *smu)
|
||||
smu_i2c->port = i;
|
||||
mutex_init(&smu_i2c->mutex);
|
||||
control->owner = THIS_MODULE;
|
||||
control->class = I2C_CLASS_SPD;
|
||||
control->dev.parent = &adev->pdev->dev;
|
||||
control->algo = &smu_v13_0_6_i2c_algo;
|
||||
snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i);
|
||||
|
@ -120,7 +120,6 @@ struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev)
|
||||
return NULL;
|
||||
|
||||
i2c->adapter.owner = THIS_MODULE;
|
||||
i2c->adapter.class = I2C_CLASS_DDC;
|
||||
i2c->adapter.dev.parent = dev->dev;
|
||||
i2c->dev = dev;
|
||||
i2c_set_adapdata(&i2c->adapter, i2c);
|
||||
|
@ -515,7 +515,6 @@ static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi)
|
||||
init_completion(&i2c->cmp);
|
||||
|
||||
adap = &i2c->adap;
|
||||
adap->class = I2C_CLASS_DDC;
|
||||
adap->owner = THIS_MODULE;
|
||||
adap->dev.parent = hdmi->dev;
|
||||
adap->algo = &dw_hdmi_algorithm;
|
||||
|
@ -2102,7 +2102,6 @@ int drm_dp_aux_register(struct drm_dp_aux *aux)
|
||||
if (!aux->ddc.algo)
|
||||
drm_dp_aux_init(aux);
|
||||
|
||||
aux->ddc.class = I2C_CLASS_DDC;
|
||||
aux->ddc.owner = THIS_MODULE;
|
||||
aux->ddc.dev.parent = aux->dev;
|
||||
|
||||
|
@ -5926,7 +5926,6 @@ static int drm_dp_mst_register_i2c_bus(struct drm_dp_mst_port *port)
|
||||
aux->ddc.algo_data = aux;
|
||||
aux->ddc.retries = 3;
|
||||
|
||||
aux->ddc.class = I2C_CLASS_DDC;
|
||||
aux->ddc.owner = THIS_MODULE;
|
||||
/* FIXME: set the kdev of the port's connector as parent */
|
||||
aux->ddc.dev.parent = parent_dev;
|
||||
|
@ -855,7 +855,6 @@ cdv_intel_dp_i2c_init(struct gma_connector *connector,
|
||||
|
||||
memset(&intel_dp->adapter, '\0', sizeof (intel_dp->adapter));
|
||||
intel_dp->adapter.owner = THIS_MODULE;
|
||||
intel_dp->adapter.class = I2C_CLASS_DDC;
|
||||
strncpy (intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
|
||||
intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0';
|
||||
intel_dp->adapter.algo_data = &intel_dp->algo;
|
||||
|
@ -411,7 +411,6 @@ int gma_intel_setup_gmbus(struct drm_device *dev)
|
||||
struct intel_gmbus *bus = &dev_priv->gmbus[i];
|
||||
|
||||
bus->adapter.owner = THIS_MODULE;
|
||||
bus->adapter.class = I2C_CLASS_DDC;
|
||||
snprintf(bus->adapter.name,
|
||||
sizeof(bus->adapter.name),
|
||||
"gma500 gmbus %s",
|
||||
|
@ -168,7 +168,6 @@ static struct i2c_adapter oaktrail_hdmi_i2c_adapter = {
|
||||
.name = "oaktrail_hdmi_i2c",
|
||||
.nr = 3,
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_DDC,
|
||||
.algo = &oaktrail_hdmi_i2c_algorithm,
|
||||
};
|
||||
|
||||
|
@ -2426,7 +2426,6 @@ psb_intel_sdvo_init_ddc_proxy(struct psb_intel_sdvo *sdvo,
|
||||
struct drm_device *dev)
|
||||
{
|
||||
sdvo->ddc.owner = THIS_MODULE;
|
||||
sdvo->ddc.class = I2C_CLASS_DDC;
|
||||
snprintf(sdvo->ddc.name, I2C_NAME_SIZE, "SDVO DDC proxy");
|
||||
sdvo->ddc.dev.parent = dev->dev;
|
||||
sdvo->ddc.algo_data = sdvo;
|
||||
|
@ -81,7 +81,6 @@ int hibmc_ddc_create(struct drm_device *drm_dev,
|
||||
struct hibmc_connector *connector)
|
||||
{
|
||||
connector->adapter.owner = THIS_MODULE;
|
||||
connector->adapter.class = I2C_CLASS_DDC;
|
||||
snprintf(connector->adapter.name, I2C_NAME_SIZE, "HIS i2c bit bus");
|
||||
connector->adapter.dev.parent = drm_dev->dev;
|
||||
i2c_set_adapdata(&connector->adapter, connector);
|
||||
|
@ -899,7 +899,6 @@ int intel_gmbus_setup(struct drm_i915_private *i915)
|
||||
}
|
||||
|
||||
bus->adapter.owner = THIS_MODULE;
|
||||
bus->adapter.class = I2C_CLASS_DDC;
|
||||
snprintf(bus->adapter.name,
|
||||
sizeof(bus->adapter.name),
|
||||
"i915 gmbus %s", gmbus_pin->name);
|
||||
|
@ -3327,7 +3327,6 @@ intel_sdvo_init_ddc_proxy(struct intel_sdvo_ddc *ddc,
|
||||
ddc->ddc_bus = ddc_bus;
|
||||
|
||||
ddc->ddc.owner = THIS_MODULE;
|
||||
ddc->ddc.class = I2C_CLASS_DDC;
|
||||
snprintf(ddc->ddc.name, I2C_NAME_SIZE, "SDVO %c DDC%d",
|
||||
port_name(sdvo->base.port), ddc_bus);
|
||||
ddc->ddc.dev.parent = &pdev->dev;
|
||||
|
@ -154,7 +154,6 @@ int lsdc_create_i2c_chan(struct drm_device *ddev,
|
||||
adapter = &li2c->adapter;
|
||||
adapter->algo_data = &li2c->bit;
|
||||
adapter->owner = THIS_MODULE;
|
||||
adapter->class = I2C_CLASS_DDC;
|
||||
adapter->dev.parent = ddev->dev;
|
||||
adapter->nr = -1;
|
||||
|
||||
|
@ -297,7 +297,6 @@ static int mtk_hdmi_ddc_probe(struct platform_device *pdev)
|
||||
|
||||
strscpy(ddc->adap.name, "mediatek-hdmi-ddc", sizeof(ddc->adap.name));
|
||||
ddc->adap.owner = THIS_MODULE;
|
||||
ddc->adap.class = I2C_CLASS_DDC;
|
||||
ddc->adap.algo = &mtk_hdmi_ddc_algorithm;
|
||||
ddc->adap.retries = 3;
|
||||
ddc->adap.dev.of_node = dev->of_node;
|
||||
|
@ -106,7 +106,6 @@ int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c)
|
||||
i2c->data = BIT(info->i2c.data_bit);
|
||||
i2c->clock = BIT(info->i2c.clock_bit);
|
||||
i2c->adapter.owner = THIS_MODULE;
|
||||
i2c->adapter.class = I2C_CLASS_DDC;
|
||||
i2c->adapter.dev.parent = dev->dev;
|
||||
i2c->dev = dev;
|
||||
i2c_set_adapdata(&i2c->adapter, i2c);
|
||||
|
@ -249,7 +249,6 @@ struct i2c_adapter *msm_hdmi_i2c_init(struct hdmi *hdmi)
|
||||
|
||||
|
||||
i2c->owner = THIS_MODULE;
|
||||
i2c->class = I2C_CLASS_DDC;
|
||||
snprintf(i2c->name, sizeof(i2c->name), "msm hdmi i2c");
|
||||
i2c->dev.parent = &hdmi->pdev->dev;
|
||||
i2c->algo = &msm_hdmi_i2c_algorithm;
|
||||
|
@ -918,7 +918,6 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
|
||||
|
||||
i2c->rec = *rec;
|
||||
i2c->adapter.owner = THIS_MODULE;
|
||||
i2c->adapter.class = I2C_CLASS_DDC;
|
||||
i2c->adapter.dev.parent = dev->dev;
|
||||
i2c->dev = dev;
|
||||
i2c_set_adapdata(&i2c->adapter, i2c);
|
||||
|
@ -792,7 +792,6 @@ static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
|
||||
init_completion(&i2c->cmp);
|
||||
|
||||
adap = &i2c->adap;
|
||||
adap->class = I2C_CLASS_DDC;
|
||||
adap->owner = THIS_MODULE;
|
||||
adap->dev.parent = hdmi->dev;
|
||||
adap->dev.of_node = hdmi->dev->of_node;
|
||||
|
@ -715,7 +715,6 @@ static struct i2c_adapter *rk3066_hdmi_i2c_adapter(struct rk3066_hdmi *hdmi)
|
||||
init_completion(&i2c->cmpltn);
|
||||
|
||||
adap = &i2c->adap;
|
||||
adap->class = I2C_CLASS_DDC;
|
||||
adap->owner = THIS_MODULE;
|
||||
adap->dev.parent = hdmi->dev;
|
||||
adap->dev.of_node = hdmi->dev->of_node;
|
||||
|
@ -302,7 +302,6 @@ int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi)
|
||||
return -ENOMEM;
|
||||
|
||||
adap->owner = THIS_MODULE;
|
||||
adap->class = I2C_CLASS_DDC;
|
||||
adap->algo = &sun4i_hdmi_i2c_algorithm;
|
||||
strscpy(adap->name, "sun4i_hdmi_i2c adapter", sizeof(adap->name));
|
||||
i2c_set_adapdata(adap, hdmi);
|
||||
|
@ -477,7 +477,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter ali1535_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
||||
|
@ -390,7 +390,7 @@ static const struct i2c_algorithm ali1563_algorithm = {
|
||||
|
||||
static struct i2c_adapter ali1563_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &ali1563_algorithm,
|
||||
};
|
||||
|
||||
|
@ -461,7 +461,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter ali15x3_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
||||
|
@ -285,7 +285,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
struct i2c_adapter amd756_smbus = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
||||
|
@ -449,7 +449,7 @@ static int amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
smbus->adapter.owner = THIS_MODULE;
|
||||
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
|
||||
"SMBus2 AMD8111 adapter at %04x", smbus->base);
|
||||
smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
smbus->adapter.class = I2C_CLASS_HWMON;
|
||||
smbus->adapter.algo = &smbus_algorithm;
|
||||
smbus->adapter.algo_data = smbus;
|
||||
|
||||
|
@ -658,7 +658,7 @@ static int cpm_i2c_probe(struct platform_device *ofdev)
|
||||
/* register new adapter to i2c module... */
|
||||
|
||||
data = of_get_property(ofdev->dev.of_node, "linux,i2c-index", &len);
|
||||
cpm->adap.nr = (data && len == 4) ? be32_to_cpup(data) : -1;
|
||||
cpm->adap.nr = (data && len == 4) ? *data : -1;
|
||||
result = i2c_add_numbered_adapter(&cpm->adap);
|
||||
|
||||
if (result < 0)
|
||||
|
@ -188,7 +188,7 @@ static struct i2c_algo_pcf_data pcf_isa_data = {
|
||||
|
||||
static struct i2c_adapter pcf_isa_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo_data = &pcf_isa_data,
|
||||
.name = "i2c-elektor",
|
||||
};
|
||||
|
@ -25,7 +25,6 @@ struct i2c_gpio_private_data {
|
||||
struct i2c_algo_bit_data bit_data;
|
||||
struct i2c_gpio_platform_data pdata;
|
||||
#ifdef CONFIG_I2C_GPIO_FAULT_INJECTOR
|
||||
struct dentry *debug_dir;
|
||||
/* these must be protected by bus lock */
|
||||
struct completion scl_irq_completion;
|
||||
u64 scl_irq_data;
|
||||
@ -72,7 +71,6 @@ static int i2c_gpio_getscl(void *data)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_I2C_GPIO_FAULT_INJECTOR
|
||||
static struct dentry *i2c_gpio_debug_dir;
|
||||
|
||||
#define setsda(bd, val) ((bd)->setsda((bd)->data, val))
|
||||
#define setscl(bd, val) ((bd)->setscl((bd)->data, val))
|
||||
@ -258,41 +256,23 @@ static void i2c_gpio_fault_injector_init(struct platform_device *pdev)
|
||||
{
|
||||
struct i2c_gpio_private_data *priv = platform_get_drvdata(pdev);
|
||||
|
||||
/*
|
||||
* If there will be a debugfs-dir per i2c adapter somewhen, put the
|
||||
* 'fault-injector' dir there. Until then, we have a global dir with
|
||||
* all adapters as subdirs.
|
||||
*/
|
||||
if (!i2c_gpio_debug_dir)
|
||||
i2c_gpio_debug_dir = debugfs_create_dir("i2c-fault-injector", NULL);
|
||||
|
||||
priv->debug_dir = debugfs_create_dir(pdev->name, i2c_gpio_debug_dir);
|
||||
|
||||
init_completion(&priv->scl_irq_completion);
|
||||
|
||||
debugfs_create_file_unsafe("incomplete_address_phase", 0200, priv->debug_dir,
|
||||
debugfs_create_file_unsafe("incomplete_address_phase", 0200, priv->adap.debugfs,
|
||||
priv, &fops_incomplete_addr_phase);
|
||||
debugfs_create_file_unsafe("incomplete_write_byte", 0200, priv->debug_dir,
|
||||
debugfs_create_file_unsafe("incomplete_write_byte", 0200, priv->adap.debugfs,
|
||||
priv, &fops_incomplete_write_byte);
|
||||
if (priv->bit_data.getscl) {
|
||||
debugfs_create_file_unsafe("inject_panic", 0200, priv->debug_dir,
|
||||
debugfs_create_file_unsafe("inject_panic", 0200, priv->adap.debugfs,
|
||||
priv, &fops_inject_panic);
|
||||
debugfs_create_file_unsafe("lose_arbitration", 0200, priv->debug_dir,
|
||||
debugfs_create_file_unsafe("lose_arbitration", 0200, priv->adap.debugfs,
|
||||
priv, &fops_lose_arbitration);
|
||||
}
|
||||
debugfs_create_file_unsafe("scl", 0600, priv->debug_dir, priv, &fops_scl);
|
||||
debugfs_create_file_unsafe("sda", 0600, priv->debug_dir, priv, &fops_sda);
|
||||
}
|
||||
|
||||
static void i2c_gpio_fault_injector_exit(struct platform_device *pdev)
|
||||
{
|
||||
struct i2c_gpio_private_data *priv = platform_get_drvdata(pdev);
|
||||
|
||||
debugfs_remove_recursive(priv->debug_dir);
|
||||
debugfs_create_file_unsafe("scl", 0600, priv->adap.debugfs, priv, &fops_scl);
|
||||
debugfs_create_file_unsafe("sda", 0600, priv->adap.debugfs, priv, &fops_sda);
|
||||
}
|
||||
#else
|
||||
static inline void i2c_gpio_fault_injector_init(struct platform_device *pdev) {}
|
||||
static inline void i2c_gpio_fault_injector_exit(struct platform_device *pdev) {}
|
||||
#endif /* CONFIG_I2C_GPIO_FAULT_INJECTOR*/
|
||||
|
||||
/* Get i2c-gpio properties from DT or ACPI table */
|
||||
@ -444,7 +424,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)
|
||||
snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
|
||||
|
||||
adap->algo_data = bit_data;
|
||||
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
adap->class = I2C_CLASS_HWMON;
|
||||
adap->dev.parent = dev;
|
||||
device_set_node(&adap->dev, fwnode);
|
||||
|
||||
@ -475,8 +455,6 @@ static void i2c_gpio_remove(struct platform_device *pdev)
|
||||
struct i2c_gpio_private_data *priv;
|
||||
struct i2c_adapter *adap;
|
||||
|
||||
i2c_gpio_fault_injector_exit(pdev);
|
||||
|
||||
priv = platform_get_drvdata(pdev);
|
||||
adap = &priv->adap;
|
||||
|
||||
|
@ -1230,8 +1230,10 @@ static const struct {
|
||||
* Additional individual entries were added after verification.
|
||||
*/
|
||||
{ "Latitude 5480", 0x29 },
|
||||
{ "Precision 3540", 0x29 },
|
||||
{ "Vostro V131", 0x1d },
|
||||
{ "Vostro 5568", 0x29 },
|
||||
{ "XPS 15 7590", 0x29 },
|
||||
};
|
||||
|
||||
static void register_dell_lis3lv02d_i2c_device(struct i801_priv *priv)
|
||||
|
@ -739,7 +739,7 @@ static int iic_probe(struct platform_device *ofdev)
|
||||
adap->dev.of_node = of_node_get(np);
|
||||
strscpy(adap->name, "IBM IIC", sizeof(adap->name));
|
||||
i2c_set_adapdata(adap, dev);
|
||||
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
adap->class = I2C_CLASS_HWMON;
|
||||
adap->algo = &iic_algo;
|
||||
adap->timeout = HZ;
|
||||
|
||||
|
@ -1401,7 +1401,7 @@ static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
|
||||
PINCTRL_STATE_DEFAULT);
|
||||
i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
|
||||
"gpio");
|
||||
rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
|
||||
rinfo->sda_gpiod = devm_gpiod_get_optional(&pdev->dev, "sda", GPIOD_IN);
|
||||
rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
|
||||
|
||||
if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER ||
|
||||
|
@ -478,7 +478,7 @@ iop3xx_i2c_probe(struct platform_device *pdev)
|
||||
|
||||
memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
|
||||
new_adapter->owner = THIS_MODULE;
|
||||
new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
new_adapter->class = I2C_CLASS_HWMON;
|
||||
new_adapter->dev.parent = &pdev->dev;
|
||||
new_adapter->dev.of_node = pdev->dev.of_node;
|
||||
new_adapter->nr = pdev->id;
|
||||
|
@ -249,7 +249,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter sch_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
||||
|
@ -283,8 +283,7 @@ static const struct i2c_algorithm kempld_i2c_algorithm = {
|
||||
static const struct i2c_adapter kempld_i2c_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "i2c-kempld",
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD |
|
||||
I2C_CLASS_DEPRECATED,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED,
|
||||
.algo = &kempld_i2c_algorithm,
|
||||
};
|
||||
|
||||
|
@ -477,7 +477,7 @@ static const struct i2c_adapter_quirks mlxcpld_i2c_quirks_ext2 = {
|
||||
static struct i2c_adapter mlxcpld_i2c_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "i2c-mlxcpld",
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &mlxcpld_i2c_algo,
|
||||
.quirks = &mlxcpld_i2c_quirks,
|
||||
.retries = MLXCPLD_I2C_RETR_NUM,
|
||||
|
@ -349,7 +349,7 @@ static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg,
|
||||
return -EBUSY;
|
||||
}
|
||||
smbus->adapter.owner = THIS_MODULE;
|
||||
smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
smbus->adapter.class = I2C_CLASS_HWMON;
|
||||
smbus->adapter.algo = &smbus_algorithm;
|
||||
smbus->adapter.algo_data = smbus;
|
||||
smbus->adapter.dev.parent = &dev->dev;
|
||||
|
@ -326,7 +326,6 @@ struct npcm_i2c {
|
||||
u8 slv_rd_buf[MAX_I2C_HW_FIFO_SIZE];
|
||||
u8 slv_wr_buf[MAX_I2C_HW_FIFO_SIZE];
|
||||
#endif
|
||||
struct dentry *debugfs; /* debugfs device directory */
|
||||
u64 ber_cnt;
|
||||
u64 rec_succ_cnt;
|
||||
u64 rec_fail_cnt;
|
||||
@ -2250,27 +2249,15 @@ static const struct i2c_algorithm npcm_i2c_algo = {
|
||||
#endif
|
||||
};
|
||||
|
||||
/* i2c debugfs directory: used to keep health monitor of i2c devices */
|
||||
static struct dentry *npcm_i2c_debugfs_dir;
|
||||
|
||||
static void npcm_i2c_init_debugfs(struct platform_device *pdev,
|
||||
struct npcm_i2c *bus)
|
||||
{
|
||||
struct dentry *d;
|
||||
|
||||
if (!npcm_i2c_debugfs_dir)
|
||||
return;
|
||||
d = debugfs_create_dir(dev_name(&pdev->dev), npcm_i2c_debugfs_dir);
|
||||
if (IS_ERR_OR_NULL(d))
|
||||
return;
|
||||
debugfs_create_u64("ber_cnt", 0444, d, &bus->ber_cnt);
|
||||
debugfs_create_u64("nack_cnt", 0444, d, &bus->nack_cnt);
|
||||
debugfs_create_u64("rec_succ_cnt", 0444, d, &bus->rec_succ_cnt);
|
||||
debugfs_create_u64("rec_fail_cnt", 0444, d, &bus->rec_fail_cnt);
|
||||
debugfs_create_u64("timeout_cnt", 0444, d, &bus->timeout_cnt);
|
||||
debugfs_create_u64("tx_complete_cnt", 0444, d, &bus->tx_complete_cnt);
|
||||
|
||||
bus->debugfs = d;
|
||||
debugfs_create_u64("ber_cnt", 0444, bus->adap.debugfs, &bus->ber_cnt);
|
||||
debugfs_create_u64("nack_cnt", 0444, bus->adap.debugfs, &bus->nack_cnt);
|
||||
debugfs_create_u64("rec_succ_cnt", 0444, bus->adap.debugfs, &bus->rec_succ_cnt);
|
||||
debugfs_create_u64("rec_fail_cnt", 0444, bus->adap.debugfs, &bus->rec_fail_cnt);
|
||||
debugfs_create_u64("timeout_cnt", 0444, bus->adap.debugfs, &bus->timeout_cnt);
|
||||
debugfs_create_u64("tx_complete_cnt", 0444, bus->adap.debugfs, &bus->tx_complete_cnt);
|
||||
}
|
||||
|
||||
static int npcm_i2c_probe_bus(struct platform_device *pdev)
|
||||
@ -2362,7 +2349,6 @@ static void npcm_i2c_remove_bus(struct platform_device *pdev)
|
||||
unsigned long lock_flags;
|
||||
struct npcm_i2c *bus = platform_get_drvdata(pdev);
|
||||
|
||||
debugfs_remove_recursive(bus->debugfs);
|
||||
spin_lock_irqsave(&bus->lock, lock_flags);
|
||||
npcm_i2c_disable(bus);
|
||||
spin_unlock_irqrestore(&bus->lock, lock_flags);
|
||||
@ -2385,28 +2371,7 @@ static struct platform_driver npcm_i2c_bus_driver = {
|
||||
}
|
||||
};
|
||||
|
||||
static int __init npcm_i2c_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
npcm_i2c_debugfs_dir = debugfs_create_dir("npcm_i2c", NULL);
|
||||
|
||||
ret = platform_driver_register(&npcm_i2c_bus_driver);
|
||||
if (ret) {
|
||||
debugfs_remove_recursive(npcm_i2c_debugfs_dir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(npcm_i2c_init);
|
||||
|
||||
static void __exit npcm_i2c_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&npcm_i2c_bus_driver);
|
||||
debugfs_remove_recursive(npcm_i2c_debugfs_dir);
|
||||
}
|
||||
module_exit(npcm_i2c_exit);
|
||||
module_platform_driver(npcm_i2c_bus_driver);
|
||||
|
||||
MODULE_AUTHOR("Avi Fishman <avi.fishman@gmail.com>");
|
||||
MODULE_AUTHOR("Tali Perry <tali.perry@nuvoton.com>");
|
||||
|
@ -56,7 +56,7 @@ static int pasemi_smb_pci_probe(struct pci_dev *dev,
|
||||
if (!smbus->ioaddr)
|
||||
return -EBUSY;
|
||||
|
||||
smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
smbus->adapter.class = I2C_CLASS_HWMON;
|
||||
error = pasemi_i2c_common_probe(smbus);
|
||||
if (error)
|
||||
return error;
|
||||
|
@ -943,7 +943,7 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
|
||||
}
|
||||
|
||||
adap->owner = THIS_MODULE;
|
||||
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
adap->class = I2C_CLASS_HWMON;
|
||||
adap->algo = sb800_main ? &piix4_smbus_algorithm_sb800
|
||||
: &smbus_algorithm;
|
||||
|
||||
|
@ -89,6 +89,7 @@
|
||||
#define TMDMAE BIT(0) /* DMA Master Transmitted Enable */
|
||||
|
||||
/* ICCCR2 */
|
||||
#define FMPE BIT(7) /* Fast Mode Plus Enable */
|
||||
#define CDFD BIT(2) /* CDF Disable */
|
||||
#define HLSE BIT(1) /* HIGH/LOW Separate Control Enable */
|
||||
#define SME BIT(0) /* SCL Mask Enable */
|
||||
@ -122,16 +123,18 @@
|
||||
#define ID_NACK BIT(4)
|
||||
#define ID_EPROTO BIT(5)
|
||||
/* persistent flags */
|
||||
#define ID_P_FMPLUS BIT(27)
|
||||
#define ID_P_NOT_ATOMIC BIT(28)
|
||||
#define ID_P_HOST_NOTIFY BIT(29)
|
||||
#define ID_P_NO_RXDMA BIT(30) /* HW forbids RXDMA sometimes */
|
||||
#define ID_P_PM_BLOCKED BIT(31)
|
||||
#define ID_P_MASK GENMASK(31, 28)
|
||||
#define ID_P_MASK GENMASK(31, 27)
|
||||
|
||||
enum rcar_i2c_type {
|
||||
I2C_RCAR_GEN1,
|
||||
I2C_RCAR_GEN2,
|
||||
I2C_RCAR_GEN3,
|
||||
I2C_RCAR_GEN4,
|
||||
};
|
||||
|
||||
struct rcar_i2c_priv {
|
||||
@ -148,6 +151,7 @@ struct rcar_i2c_priv {
|
||||
u32 icccr;
|
||||
u16 schd;
|
||||
u16 scld;
|
||||
u8 smd;
|
||||
u8 recovery_icmcr; /* protected by adapter lock */
|
||||
enum rcar_i2c_type devtype;
|
||||
struct i2c_client *slave;
|
||||
@ -239,9 +243,14 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
|
||||
if (priv->devtype < I2C_RCAR_GEN3) {
|
||||
rcar_i2c_write(priv, ICCCR, priv->icccr);
|
||||
} else {
|
||||
rcar_i2c_write(priv, ICCCR2, CDFD | HLSE | SME);
|
||||
u32 icccr2 = CDFD | HLSE | SME;
|
||||
|
||||
if (priv->flags & ID_P_FMPLUS)
|
||||
icccr2 |= FMPE;
|
||||
|
||||
rcar_i2c_write(priv, ICCCR2, icccr2);
|
||||
rcar_i2c_write(priv, ICCCR, priv->icccr);
|
||||
rcar_i2c_write(priv, ICMPR, RCAR_DEFAULT_SMD);
|
||||
rcar_i2c_write(priv, ICMPR, priv->smd);
|
||||
rcar_i2c_write(priv, ICHPR, priv->schd);
|
||||
rcar_i2c_write(priv, ICLPR, priv->scld);
|
||||
rcar_i2c_write(priv, ICFBSCR, TCYC17);
|
||||
@ -278,6 +287,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv)
|
||||
|
||||
/* Fall back to previously used values if not supplied */
|
||||
i2c_parse_fw_timings(dev, &t, false);
|
||||
priv->smd = RCAR_DEFAULT_SMD;
|
||||
|
||||
/*
|
||||
* calculate SCL clock
|
||||
@ -303,6 +313,11 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv)
|
||||
if (cdf >= 1U << cdf_width)
|
||||
goto err_no_val;
|
||||
|
||||
if (t.bus_freq_hz > I2C_MAX_FAST_MODE_FREQ && priv->devtype >= I2C_RCAR_GEN4)
|
||||
priv->flags |= ID_P_FMPLUS;
|
||||
else
|
||||
priv->flags &= ~ID_P_FMPLUS;
|
||||
|
||||
/* On Gen3+, we use cdf only for the filters, not as a SCL divider */
|
||||
ick = rate / (priv->devtype < I2C_RCAR_GEN3 ? (cdf + 1) : 1);
|
||||
|
||||
@ -344,30 +359,30 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv)
|
||||
* x as a base value for the SCLD/SCHD ratio:
|
||||
*
|
||||
* SCL = clkp / (8 + 2 * SMD + SCLD + SCHD + F[(ticf + tr + intd) * clkp])
|
||||
* SCL = clkp / (8 + 2 * RCAR_DEFAULT_SMD + RCAR_SCLD_RATIO * x
|
||||
* SCL = clkp / (8 + 2 * SMD + RCAR_SCLD_RATIO * x
|
||||
* + RCAR_SCHD_RATIO * x + F[...])
|
||||
*
|
||||
* with: sum_ratio = RCAR_SCLD_RATIO + RCAR_SCHD_RATIO
|
||||
* and: smd = RCAR_DEFAULT_SMD
|
||||
*
|
||||
* SCL = clkp / (8 + 2 * smd + sum_ratio * x + F[...])
|
||||
* 8 + 2 * smd + sum_ratio * x + F[...] = clkp / SCL
|
||||
* x = ((clkp / SCL) - 8 - 2 * smd - F[...]) / sum_ratio
|
||||
*/
|
||||
x = DIV_ROUND_UP(rate, t.bus_freq_hz ?: 1);
|
||||
x = DIV_ROUND_UP(x - 8 - 2 * RCAR_DEFAULT_SMD - round, sum_ratio);
|
||||
scl = rate / (8 + 2 * RCAR_DEFAULT_SMD + sum_ratio * x + round);
|
||||
x = DIV_ROUND_UP(x - 8 - 2 * priv->smd - round, sum_ratio);
|
||||
scl = rate / (8 + 2 * priv->smd + sum_ratio * x + round);
|
||||
|
||||
/* Bail out if values don't fit into 16 bit or SMD became too large */
|
||||
if (x * RCAR_SCLD_RATIO > 0xffff || RCAR_DEFAULT_SMD > x * RCAR_SCHD_RATIO)
|
||||
if (x == 0 || x * RCAR_SCLD_RATIO > 0xffff)
|
||||
goto err_no_val;
|
||||
|
||||
priv->icccr = cdf;
|
||||
priv->schd = RCAR_SCHD_RATIO * x;
|
||||
priv->scld = RCAR_SCLD_RATIO * x;
|
||||
if (priv->smd >= priv->schd)
|
||||
priv->smd = priv->schd - 1;
|
||||
|
||||
dev_dbg(dev, "clk %u/%u(%lu), round %u, CDF: %u SCHD %u SCLD %u\n",
|
||||
scl, t.bus_freq_hz, rate, round, cdf, priv->schd, priv->scld);
|
||||
dev_dbg(dev, "clk %u/%u(%lu), round %u, CDF: %u SCHD %u SCLD %u SMD %u\n",
|
||||
scl, t.bus_freq_hz, rate, round, cdf, priv->schd, priv->scld, priv->smd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -431,8 +446,8 @@ static void rcar_i2c_cleanup_dma(struct rcar_i2c_priv *priv, bool terminate)
|
||||
dma_unmap_single(chan->device->dev, sg_dma_address(&priv->sg),
|
||||
sg_dma_len(&priv->sg), priv->dma_direction);
|
||||
|
||||
/* Gen3 can only do one RXDMA per transfer and we just completed it */
|
||||
if (priv->devtype == I2C_RCAR_GEN3 &&
|
||||
/* Gen3+ can only do one RXDMA per transfer and we just completed it */
|
||||
if (priv->devtype >= I2C_RCAR_GEN3 &&
|
||||
priv->dma_direction == DMA_FROM_DEVICE)
|
||||
priv->flags |= ID_P_NO_RXDMA;
|
||||
|
||||
@ -886,8 +901,8 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* Gen3 needs a reset before allowing RXDMA once */
|
||||
if (priv->devtype == I2C_RCAR_GEN3) {
|
||||
/* Gen3+ needs a reset. That also allows RXDMA once */
|
||||
if (priv->devtype >= I2C_RCAR_GEN3) {
|
||||
priv->flags &= ~ID_P_NO_RXDMA;
|
||||
ret = rcar_i2c_do_reset(priv);
|
||||
if (ret)
|
||||
@ -1072,10 +1087,12 @@ static const struct of_device_id rcar_i2c_dt_ids[] = {
|
||||
{ .compatible = "renesas,i2c-r8a7794", .data = (void *)I2C_RCAR_GEN2 },
|
||||
{ .compatible = "renesas,i2c-r8a7795", .data = (void *)I2C_RCAR_GEN3 },
|
||||
{ .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 },
|
||||
/* S4 has no FM+ bit */
|
||||
{ .compatible = "renesas,i2c-r8a779f0", .data = (void *)I2C_RCAR_GEN3 },
|
||||
{ .compatible = "renesas,rcar-gen1-i2c", .data = (void *)I2C_RCAR_GEN1 },
|
||||
{ .compatible = "renesas,rcar-gen2-i2c", .data = (void *)I2C_RCAR_GEN2 },
|
||||
{ .compatible = "renesas,rcar-gen3-i2c", .data = (void *)I2C_RCAR_GEN3 },
|
||||
{ .compatible = "renesas,rcar-gen4-i2c", .data = (void *)I2C_RCAR_GEN3 },
|
||||
{ .compatible = "renesas,rcar-gen4-i2c", .data = (void *)I2C_RCAR_GEN4 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids);
|
||||
@ -1151,7 +1168,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
|
||||
if (of_property_read_bool(dev->of_node, "smbus"))
|
||||
priv->flags |= ID_P_HOST_NOTIFY;
|
||||
|
||||
if (priv->devtype == I2C_RCAR_GEN3) {
|
||||
if (priv->devtype >= I2C_RCAR_GEN3) {
|
||||
priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
|
||||
if (IS_ERR(priv->rstc)) {
|
||||
ret = PTR_ERR(priv->rstc);
|
||||
|
@ -1295,8 +1295,12 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* 27+i: write mask, 11+i: value */
|
||||
value = BIT(27 + bus_nr) | BIT(11 + bus_nr);
|
||||
/* rv1126 i2c2 uses non-sequential write mask 20, value 4 */
|
||||
if (i2c->soc_data == &rv1126_soc_data && bus_nr == 2)
|
||||
value = BIT(20) | BIT(4);
|
||||
else
|
||||
/* 27+i: write mask, 11+i: value */
|
||||
value = BIT(27 + bus_nr) | BIT(11 + bus_nr);
|
||||
|
||||
ret = regmap_write(grf, i2c->soc_data->grf_offset, value);
|
||||
if (ret != 0) {
|
||||
|
@ -76,6 +76,7 @@
|
||||
#define QUIRK_HDMIPHY (1 << 1)
|
||||
#define QUIRK_NO_GPIO (1 << 2)
|
||||
#define QUIRK_POLL (1 << 3)
|
||||
#define QUIRK_ATOMIC (1 << 4)
|
||||
|
||||
/* Max time to wait for bus to become idle after a xfer (in us) */
|
||||
#define S3C2410_IDLE_TIMEOUT 5000
|
||||
@ -174,7 +175,7 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
|
||||
if (ret)
|
||||
i2c->msg_idx = ret;
|
||||
|
||||
if (!(i2c->quirks & QUIRK_POLL))
|
||||
if (!(i2c->quirks & (QUIRK_POLL | QUIRK_ATOMIC)))
|
||||
wake_up(&i2c->wait);
|
||||
}
|
||||
|
||||
@ -216,8 +217,17 @@ static bool is_ack(struct s3c24xx_i2c *i2c)
|
||||
int tries;
|
||||
|
||||
for (tries = 50; tries; --tries) {
|
||||
if (readl(i2c->regs + S3C2410_IICCON)
|
||||
& S3C2410_IICCON_IRQPEND) {
|
||||
unsigned long tmp = readl(i2c->regs + S3C2410_IICCON);
|
||||
|
||||
if (!(tmp & S3C2410_IICCON_ACKEN)) {
|
||||
/*
|
||||
* Wait a bit for the bus to stabilize,
|
||||
* delay estimated experimentally.
|
||||
*/
|
||||
usleep_range(100, 200);
|
||||
return true;
|
||||
}
|
||||
if (tmp & S3C2410_IICCON_IRQPEND) {
|
||||
if (!(readl(i2c->regs + S3C2410_IICSTAT)
|
||||
& S3C2410_IICSTAT_LASTBIT))
|
||||
return true;
|
||||
@ -270,16 +280,6 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
|
||||
|
||||
stat |= S3C2410_IICSTAT_START;
|
||||
writel(stat, i2c->regs + S3C2410_IICSTAT);
|
||||
|
||||
if (i2c->quirks & QUIRK_POLL) {
|
||||
while ((i2c->msg_num != 0) && is_ack(i2c)) {
|
||||
i2c_s3c_irq_nextbyte(i2c, stat);
|
||||
stat = readl(i2c->regs + S3C2410_IICSTAT);
|
||||
|
||||
if (stat & S3C2410_IICSTAT_ARBITR)
|
||||
dev_err(i2c->dev, "deal with arbitration loss\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
|
||||
@ -685,7 +685,7 @@ static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c)
|
||||
static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
unsigned long timeout;
|
||||
unsigned long timeout = 0;
|
||||
int ret;
|
||||
|
||||
ret = s3c24xx_i2c_set_master(i2c);
|
||||
@ -704,17 +704,20 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
|
||||
s3c24xx_i2c_enable_irq(i2c);
|
||||
s3c24xx_i2c_message_start(i2c, msgs);
|
||||
|
||||
if (i2c->quirks & QUIRK_POLL) {
|
||||
ret = i2c->msg_idx;
|
||||
if (i2c->quirks & (QUIRK_POLL | QUIRK_ATOMIC)) {
|
||||
while ((i2c->msg_num != 0) && is_ack(i2c)) {
|
||||
unsigned long stat = readl(i2c->regs + S3C2410_IICSTAT);
|
||||
|
||||
if (ret != num)
|
||||
dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
|
||||
i2c_s3c_irq_nextbyte(i2c, stat);
|
||||
|
||||
goto out;
|
||||
stat = readl(i2c->regs + S3C2410_IICSTAT);
|
||||
if (stat & S3C2410_IICSTAT_ARBITR)
|
||||
dev_err(i2c->dev, "deal with arbitration loss\n");
|
||||
}
|
||||
} else {
|
||||
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
|
||||
}
|
||||
|
||||
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
|
||||
|
||||
ret = i2c->msg_idx;
|
||||
|
||||
/*
|
||||
@ -773,6 +776,21 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
static int s3c24xx_i2c_xfer_atomic(struct i2c_adapter *adap,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
struct s3c24xx_i2c *i2c = (struct s3c24xx_i2c *)adap->algo_data;
|
||||
int ret;
|
||||
|
||||
disable_irq(i2c->irq);
|
||||
i2c->quirks |= QUIRK_ATOMIC;
|
||||
ret = s3c24xx_i2c_xfer(adap, msgs, num);
|
||||
i2c->quirks &= ~QUIRK_ATOMIC;
|
||||
enable_irq(i2c->irq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* declare our i2c functionality */
|
||||
static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
|
||||
{
|
||||
@ -783,6 +801,7 @@ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
|
||||
/* i2c bus registration info */
|
||||
static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
|
||||
.master_xfer = s3c24xx_i2c_xfer,
|
||||
.master_xfer_atomic = s3c24xx_i2c_xfer_atomic,
|
||||
.functionality = s3c24xx_i2c_func,
|
||||
};
|
||||
|
||||
|
@ -385,7 +385,7 @@ static int smbus_cmi_probe(struct platform_device *device)
|
||||
smbus_cmi->adapter.owner = THIS_MODULE;
|
||||
smbus_cmi->adapter.algo = &acpi_smbus_cmi_algorithm;
|
||||
smbus_cmi->adapter.algo_data = smbus_cmi;
|
||||
smbus_cmi->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
smbus_cmi->adapter.class = I2C_CLASS_HWMON;
|
||||
smbus_cmi->adapter.dev.parent = &device->dev;
|
||||
|
||||
ret = i2c_add_adapter(&smbus_cmi->adapter);
|
||||
|
@ -477,7 +477,7 @@ static int sh7760_i2c_probe(struct platform_device *pdev)
|
||||
|
||||
id->adap.nr = pdev->id;
|
||||
id->adap.algo = &sh7760_i2c_algo;
|
||||
id->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
id->adap.class = I2C_CLASS_HWMON;
|
||||
id->adap.retries = 3;
|
||||
id->adap.algo_data = id;
|
||||
id->adap.dev.parent = &pdev->dev;
|
||||
|
@ -142,7 +142,7 @@ static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
|
||||
static struct i2c_adapter sibyte_board_adapter[2] = {
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = NULL,
|
||||
.algo_data = &sibyte_board_data[0],
|
||||
.nr = 0,
|
||||
@ -150,7 +150,7 @@ static struct i2c_adapter sibyte_board_adapter[2] = {
|
||||
},
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = NULL,
|
||||
.algo_data = &sibyte_board_data[1],
|
||||
.nr = 1,
|
||||
|
@ -353,7 +353,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter sis5595_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
||||
|
@ -493,7 +493,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter sis630_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
.retries = 3
|
||||
};
|
||||
|
@ -228,7 +228,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter sis96x_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
||||
#define STM32F7_I2C_TXDR 0x28
|
||||
|
||||
/* STM32F7 I2C control 1 */
|
||||
#define STM32_I2C_CR1_FMP BIT(24)
|
||||
#define STM32F7_I2C_CR1_PECEN BIT(23)
|
||||
#define STM32F7_I2C_CR1_ALERTEN BIT(22)
|
||||
#define STM32F7_I2C_CR1_SMBHEN BIT(20)
|
||||
@ -226,6 +227,8 @@ struct stm32f7_i2c_spec {
|
||||
* @rise_time: Rise time (ns)
|
||||
* @fall_time: Fall time (ns)
|
||||
* @fmp_clr_offset: Fast Mode Plus clear register offset from set register
|
||||
* @single_it_line: Only a single IT line is used for both events/errors
|
||||
* @fmp_cr1_bit: Fast Mode Plus control is done via a bit in CR1
|
||||
*/
|
||||
struct stm32f7_i2c_setup {
|
||||
u32 speed_freq;
|
||||
@ -233,6 +236,8 @@ struct stm32f7_i2c_setup {
|
||||
u32 rise_time;
|
||||
u32 fall_time;
|
||||
u32 fmp_clr_offset;
|
||||
bool single_it_line;
|
||||
bool fmp_cr1_bit;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -418,6 +423,13 @@ static const struct stm32f7_i2c_setup stm32mp13_setup = {
|
||||
.fmp_clr_offset = 0x4,
|
||||
};
|
||||
|
||||
static const struct stm32f7_i2c_setup stm32mp25_setup = {
|
||||
.rise_time = STM32F7_I2C_RISE_TIME_DEFAULT,
|
||||
.fall_time = STM32F7_I2C_FALL_TIME_DEFAULT,
|
||||
.single_it_line = true,
|
||||
.fmp_cr1_bit = true,
|
||||
};
|
||||
|
||||
static inline void stm32f7_i2c_set_bits(void __iomem *reg, u32 mask)
|
||||
{
|
||||
writel_relaxed(readl_relaxed(reg) | mask, reg);
|
||||
@ -1419,15 +1431,13 @@ static bool stm32f7_i2c_is_slave_busy(struct stm32f7_i2c_dev *i2c_dev)
|
||||
return i == busy;
|
||||
}
|
||||
|
||||
static irqreturn_t stm32f7_i2c_slave_isr_event(struct stm32f7_i2c_dev *i2c_dev)
|
||||
static irqreturn_t stm32f7_i2c_slave_isr_event(struct stm32f7_i2c_dev *i2c_dev, u32 status)
|
||||
{
|
||||
void __iomem *base = i2c_dev->base;
|
||||
u32 cr2, status, mask;
|
||||
u32 cr2, mask;
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
|
||||
|
||||
/* Slave transmitter mode */
|
||||
if (status & STM32F7_I2C_ISR_TXIS) {
|
||||
i2c_slave_event(i2c_dev->slave_running,
|
||||
@ -1494,142 +1504,17 @@ static irqreturn_t stm32f7_i2c_slave_isr_event(struct stm32f7_i2c_dev *i2c_dev)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
|
||||
static irqreturn_t stm32f7_i2c_handle_isr_errs(struct stm32f7_i2c_dev *i2c_dev, u32 status)
|
||||
{
|
||||
struct stm32f7_i2c_dev *i2c_dev = data;
|
||||
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
|
||||
struct stm32_i2c_dma *dma = i2c_dev->dma;
|
||||
void __iomem *base = i2c_dev->base;
|
||||
u32 status, mask;
|
||||
int ret = IRQ_HANDLED;
|
||||
|
||||
/* Check if the interrupt if for a slave device */
|
||||
if (!i2c_dev->master_mode) {
|
||||
ret = stm32f7_i2c_slave_isr_event(i2c_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
|
||||
|
||||
/* Tx empty */
|
||||
if (status & STM32F7_I2C_ISR_TXIS)
|
||||
stm32f7_i2c_write_tx_data(i2c_dev);
|
||||
|
||||
/* RX not empty */
|
||||
if (status & STM32F7_I2C_ISR_RXNE)
|
||||
stm32f7_i2c_read_rx_data(i2c_dev);
|
||||
|
||||
/* NACK received */
|
||||
if (status & STM32F7_I2C_ISR_NACKF) {
|
||||
dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n",
|
||||
__func__, f7_msg->addr);
|
||||
writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR);
|
||||
if (i2c_dev->use_dma) {
|
||||
stm32f7_i2c_disable_dma_req(i2c_dev);
|
||||
dmaengine_terminate_async(dma->chan_using);
|
||||
}
|
||||
f7_msg->result = -ENXIO;
|
||||
}
|
||||
|
||||
/* STOP detection flag */
|
||||
if (status & STM32F7_I2C_ISR_STOPF) {
|
||||
/* Disable interrupts */
|
||||
if (stm32f7_i2c_is_slave_registered(i2c_dev))
|
||||
mask = STM32F7_I2C_XFER_IRQ_MASK;
|
||||
else
|
||||
mask = STM32F7_I2C_ALL_IRQ_MASK;
|
||||
stm32f7_i2c_disable_irq(i2c_dev, mask);
|
||||
|
||||
/* Clear STOP flag */
|
||||
writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
|
||||
|
||||
if (i2c_dev->use_dma && !f7_msg->result) {
|
||||
ret = IRQ_WAKE_THREAD;
|
||||
} else {
|
||||
i2c_dev->master_mode = false;
|
||||
complete(&i2c_dev->complete);
|
||||
}
|
||||
}
|
||||
|
||||
/* Transfer complete */
|
||||
if (status & STM32F7_I2C_ISR_TC) {
|
||||
if (f7_msg->stop) {
|
||||
mask = STM32F7_I2C_CR2_STOP;
|
||||
stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
|
||||
} else if (i2c_dev->use_dma && !f7_msg->result) {
|
||||
ret = IRQ_WAKE_THREAD;
|
||||
} else if (f7_msg->smbus) {
|
||||
stm32f7_i2c_smbus_rep_start(i2c_dev);
|
||||
} else {
|
||||
i2c_dev->msg_id++;
|
||||
i2c_dev->msg++;
|
||||
stm32f7_i2c_xfer_msg(i2c_dev, i2c_dev->msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & STM32F7_I2C_ISR_TCR) {
|
||||
if (f7_msg->smbus)
|
||||
stm32f7_i2c_smbus_reload(i2c_dev);
|
||||
else
|
||||
stm32f7_i2c_reload(i2c_dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)
|
||||
{
|
||||
struct stm32f7_i2c_dev *i2c_dev = data;
|
||||
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
|
||||
struct stm32_i2c_dma *dma = i2c_dev->dma;
|
||||
u32 status;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Wait for dma transfer completion before sending next message or
|
||||
* notity the end of xfer to the client
|
||||
*/
|
||||
ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ);
|
||||
if (!ret) {
|
||||
dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__);
|
||||
stm32f7_i2c_disable_dma_req(i2c_dev);
|
||||
dmaengine_terminate_async(dma->chan_using);
|
||||
f7_msg->result = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
|
||||
|
||||
if (status & STM32F7_I2C_ISR_TC) {
|
||||
if (f7_msg->smbus) {
|
||||
stm32f7_i2c_smbus_rep_start(i2c_dev);
|
||||
} else {
|
||||
i2c_dev->msg_id++;
|
||||
i2c_dev->msg++;
|
||||
stm32f7_i2c_xfer_msg(i2c_dev, i2c_dev->msg);
|
||||
}
|
||||
} else {
|
||||
i2c_dev->master_mode = false;
|
||||
complete(&i2c_dev->complete);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
|
||||
{
|
||||
struct stm32f7_i2c_dev *i2c_dev = data;
|
||||
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
|
||||
u16 addr = f7_msg->addr;
|
||||
void __iomem *base = i2c_dev->base;
|
||||
struct device *dev = i2c_dev->dev;
|
||||
struct stm32_i2c_dma *dma = i2c_dev->dma;
|
||||
u32 status;
|
||||
|
||||
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
|
||||
|
||||
/* Bus error */
|
||||
if (status & STM32F7_I2C_ISR_BERR) {
|
||||
dev_err(dev, "<%s>: Bus error accessing addr 0x%x\n",
|
||||
__func__, f7_msg->addr);
|
||||
dev_err(dev, "Bus error accessing addr 0x%x\n", addr);
|
||||
writel_relaxed(STM32F7_I2C_ICR_BERRCF, base + STM32F7_I2C_ICR);
|
||||
stm32f7_i2c_release_bus(&i2c_dev->adap);
|
||||
f7_msg->result = -EIO;
|
||||
@ -1637,21 +1522,19 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
|
||||
|
||||
/* Arbitration loss */
|
||||
if (status & STM32F7_I2C_ISR_ARLO) {
|
||||
dev_dbg(dev, "<%s>: Arbitration loss accessing addr 0x%x\n",
|
||||
__func__, f7_msg->addr);
|
||||
dev_dbg(dev, "Arbitration loss accessing addr 0x%x\n", addr);
|
||||
writel_relaxed(STM32F7_I2C_ICR_ARLOCF, base + STM32F7_I2C_ICR);
|
||||
f7_msg->result = -EAGAIN;
|
||||
}
|
||||
|
||||
if (status & STM32F7_I2C_ISR_PECERR) {
|
||||
dev_err(dev, "<%s>: PEC error in reception accessing addr 0x%x\n",
|
||||
__func__, f7_msg->addr);
|
||||
dev_err(dev, "PEC error in reception accessing addr 0x%x\n", addr);
|
||||
writel_relaxed(STM32F7_I2C_ICR_PECCF, base + STM32F7_I2C_ICR);
|
||||
f7_msg->result = -EINVAL;
|
||||
}
|
||||
|
||||
if (status & STM32F7_I2C_ISR_ALERT) {
|
||||
dev_dbg(dev, "<%s>: SMBus alert received\n", __func__);
|
||||
dev_dbg(dev, "SMBus alert received\n");
|
||||
writel_relaxed(STM32F7_I2C_ICR_ALERTCF, base + STM32F7_I2C_ICR);
|
||||
i2c_handle_smbus_alert(i2c_dev->alert->ara);
|
||||
return IRQ_HANDLED;
|
||||
@ -1679,6 +1562,130 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#define STM32F7_ERR_EVENTS (STM32F7_I2C_ISR_BERR | STM32F7_I2C_ISR_ARLO |\
|
||||
STM32F7_I2C_ISR_PECERR | STM32F7_I2C_ISR_ALERT)
|
||||
static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
|
||||
{
|
||||
struct stm32f7_i2c_dev *i2c_dev = data;
|
||||
u32 status;
|
||||
|
||||
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
|
||||
|
||||
/*
|
||||
* Check if the interrupt is for a slave device or related
|
||||
* to errors flags (in case of single it line mode)
|
||||
*/
|
||||
if (!i2c_dev->master_mode ||
|
||||
(i2c_dev->setup.single_it_line && (status & STM32F7_ERR_EVENTS)))
|
||||
return IRQ_WAKE_THREAD;
|
||||
|
||||
/* Tx empty */
|
||||
if (status & STM32F7_I2C_ISR_TXIS)
|
||||
stm32f7_i2c_write_tx_data(i2c_dev);
|
||||
|
||||
/* RX not empty */
|
||||
if (status & STM32F7_I2C_ISR_RXNE)
|
||||
stm32f7_i2c_read_rx_data(i2c_dev);
|
||||
|
||||
/* Wake up the thread if other flags are raised */
|
||||
if (status &
|
||||
(STM32F7_I2C_ISR_NACKF | STM32F7_I2C_ISR_STOPF |
|
||||
STM32F7_I2C_ISR_TC | STM32F7_I2C_ISR_TCR))
|
||||
return IRQ_WAKE_THREAD;
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)
|
||||
{
|
||||
struct stm32f7_i2c_dev *i2c_dev = data;
|
||||
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
|
||||
struct stm32_i2c_dma *dma = i2c_dev->dma;
|
||||
void __iomem *base = i2c_dev->base;
|
||||
u32 status, mask;
|
||||
int ret;
|
||||
|
||||
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
|
||||
|
||||
if (!i2c_dev->master_mode)
|
||||
return stm32f7_i2c_slave_isr_event(i2c_dev, status);
|
||||
|
||||
/* Handle errors in case of this handler is used for events/errors */
|
||||
if (i2c_dev->setup.single_it_line && (status & STM32F7_ERR_EVENTS))
|
||||
return stm32f7_i2c_handle_isr_errs(i2c_dev, status);
|
||||
|
||||
/* NACK received */
|
||||
if (status & STM32F7_I2C_ISR_NACKF) {
|
||||
dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n",
|
||||
__func__, f7_msg->addr);
|
||||
writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR);
|
||||
if (i2c_dev->use_dma) {
|
||||
stm32f7_i2c_disable_dma_req(i2c_dev);
|
||||
dmaengine_terminate_async(dma->chan_using);
|
||||
}
|
||||
f7_msg->result = -ENXIO;
|
||||
}
|
||||
|
||||
if (status & STM32F7_I2C_ISR_TCR) {
|
||||
if (f7_msg->smbus)
|
||||
stm32f7_i2c_smbus_reload(i2c_dev);
|
||||
else
|
||||
stm32f7_i2c_reload(i2c_dev);
|
||||
}
|
||||
|
||||
/* Transfer complete */
|
||||
if (status & STM32F7_I2C_ISR_TC) {
|
||||
/* Wait for dma transfer completion before sending next message */
|
||||
if (i2c_dev->use_dma && !f7_msg->result) {
|
||||
ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ);
|
||||
if (!ret) {
|
||||
dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__);
|
||||
stm32f7_i2c_disable_dma_req(i2c_dev);
|
||||
dmaengine_terminate_async(dma->chan_using);
|
||||
f7_msg->result = -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
if (f7_msg->stop) {
|
||||
mask = STM32F7_I2C_CR2_STOP;
|
||||
stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
|
||||
} else if (f7_msg->smbus) {
|
||||
stm32f7_i2c_smbus_rep_start(i2c_dev);
|
||||
} else {
|
||||
i2c_dev->msg_id++;
|
||||
i2c_dev->msg++;
|
||||
stm32f7_i2c_xfer_msg(i2c_dev, i2c_dev->msg);
|
||||
}
|
||||
}
|
||||
|
||||
/* STOP detection flag */
|
||||
if (status & STM32F7_I2C_ISR_STOPF) {
|
||||
/* Disable interrupts */
|
||||
if (stm32f7_i2c_is_slave_registered(i2c_dev))
|
||||
mask = STM32F7_I2C_XFER_IRQ_MASK;
|
||||
else
|
||||
mask = STM32F7_I2C_ALL_IRQ_MASK;
|
||||
stm32f7_i2c_disable_irq(i2c_dev, mask);
|
||||
|
||||
/* Clear STOP flag */
|
||||
writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
|
||||
|
||||
i2c_dev->master_mode = false;
|
||||
complete(&i2c_dev->complete);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data)
|
||||
{
|
||||
struct stm32f7_i2c_dev *i2c_dev = data;
|
||||
u32 status;
|
||||
|
||||
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
|
||||
|
||||
return stm32f7_i2c_handle_isr_errs(i2c_dev, status);
|
||||
}
|
||||
|
||||
static int stm32f7_i2c_wait_polling(struct stm32f7_i2c_dev *i2c_dev)
|
||||
{
|
||||
ktime_t timeout = ktime_add_ms(ktime_get(), i2c_dev->adap.timeout);
|
||||
@ -2012,23 +2019,27 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
|
||||
static int stm32f7_i2c_write_fm_plus_bits(struct stm32f7_i2c_dev *i2c_dev,
|
||||
bool enable)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (i2c_dev->bus_rate <= I2C_MAX_FAST_MODE_FREQ ||
|
||||
IS_ERR_OR_NULL(i2c_dev->regmap))
|
||||
(!i2c_dev->setup.fmp_cr1_bit && IS_ERR_OR_NULL(i2c_dev->regmap)))
|
||||
/* Optional */
|
||||
return 0;
|
||||
|
||||
if (i2c_dev->fmp_sreg == i2c_dev->fmp_creg)
|
||||
ret = regmap_update_bits(i2c_dev->regmap,
|
||||
i2c_dev->fmp_sreg,
|
||||
i2c_dev->fmp_mask,
|
||||
enable ? i2c_dev->fmp_mask : 0);
|
||||
else
|
||||
ret = regmap_write(i2c_dev->regmap,
|
||||
enable ? i2c_dev->fmp_sreg :
|
||||
i2c_dev->fmp_creg,
|
||||
i2c_dev->fmp_mask);
|
||||
if (i2c_dev->setup.fmp_cr1_bit) {
|
||||
if (enable)
|
||||
stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1, STM32_I2C_CR1_FMP);
|
||||
else
|
||||
stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, STM32_I2C_CR1_FMP);
|
||||
} else {
|
||||
if (i2c_dev->fmp_sreg == i2c_dev->fmp_creg)
|
||||
ret = regmap_update_bits(i2c_dev->regmap, i2c_dev->fmp_sreg,
|
||||
i2c_dev->fmp_mask, enable ? i2c_dev->fmp_mask : 0);
|
||||
else
|
||||
ret = regmap_write(i2c_dev->regmap,
|
||||
enable ? i2c_dev->fmp_sreg : i2c_dev->fmp_creg,
|
||||
i2c_dev->fmp_mask);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -2162,6 +2173,13 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
if (!i2c_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
setup = of_device_get_match_data(&pdev->dev);
|
||||
if (!setup) {
|
||||
dev_err(&pdev->dev, "Can't get device data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
i2c_dev->setup = *setup;
|
||||
|
||||
i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(i2c_dev->base))
|
||||
return PTR_ERR(i2c_dev->base);
|
||||
@ -2171,10 +2189,6 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
if (irq_event < 0)
|
||||
return irq_event;
|
||||
|
||||
irq_error = platform_get_irq(pdev, 1);
|
||||
if (irq_error < 0)
|
||||
return irq_error;
|
||||
|
||||
i2c_dev->wakeup_src = of_property_read_bool(pdev->dev.of_node,
|
||||
"wakeup-source");
|
||||
|
||||
@ -2199,26 +2213,22 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
stm32f7_i2c_isr_event_thread,
|
||||
IRQF_ONESHOT,
|
||||
pdev->name, i2c_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to request irq event %i\n",
|
||||
irq_event);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret, "Failed to request irq event\n");
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq_error, stm32f7_i2c_isr_error, 0,
|
||||
pdev->name, i2c_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to request irq error %i\n",
|
||||
irq_error);
|
||||
return ret;
|
||||
}
|
||||
if (!i2c_dev->setup.single_it_line) {
|
||||
irq_error = platform_get_irq(pdev, 1);
|
||||
if (irq_error < 0)
|
||||
return irq_error;
|
||||
|
||||
setup = of_device_get_match_data(&pdev->dev);
|
||||
if (!setup) {
|
||||
dev_err(&pdev->dev, "Can't get device data\n");
|
||||
return -ENODEV;
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq_error,
|
||||
NULL,
|
||||
stm32f7_i2c_isr_error_thread,
|
||||
IRQF_ONESHOT,
|
||||
pdev->name, i2c_dev);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret, "Failed to request irq error\n");
|
||||
}
|
||||
i2c_dev->setup = *setup;
|
||||
|
||||
ret = stm32f7_i2c_setup_timing(i2c_dev, &i2c_dev->setup);
|
||||
if (ret)
|
||||
@ -2226,9 +2236,12 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
|
||||
|
||||
/* Setup Fast mode plus if necessary */
|
||||
if (i2c_dev->bus_rate > I2C_MAX_FAST_MODE_FREQ) {
|
||||
ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!i2c_dev->setup.fmp_cr1_bit) {
|
||||
ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = stm32f7_i2c_write_fm_plus_bits(i2c_dev, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -2507,6 +2520,7 @@ static const struct of_device_id stm32f7_i2c_match[] = {
|
||||
{ .compatible = "st,stm32f7-i2c", .data = &stm32f7_setup},
|
||||
{ .compatible = "st,stm32mp15-i2c", .data = &stm32mp15_setup},
|
||||
{ .compatible = "st,stm32mp13-i2c", .data = &stm32mp13_setup},
|
||||
{ .compatible = "st,stm32mp25-i2c", .data = &stm32mp25_setup},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, stm32f7_i2c_match);
|
||||
|
@ -70,7 +70,7 @@ static struct i2c_algo_bit_data bit_data = {
|
||||
|
||||
static struct i2c_adapter vt586b_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.name = "VIA i2c",
|
||||
.algo_data = &bit_data,
|
||||
};
|
||||
|
@ -304,7 +304,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter vt596_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
||||
|
@ -74,9 +74,6 @@
|
||||
#define MCR_APB_96M 7
|
||||
#define MCR_APB_166M 12
|
||||
|
||||
#define I2C_MODE_STANDARD 0
|
||||
#define I2C_MODE_FAST 1
|
||||
|
||||
#define WMT_I2C_TIMEOUT (msecs_to_jiffies(1000))
|
||||
|
||||
struct wmt_i2c_dev {
|
||||
@ -85,7 +82,7 @@ struct wmt_i2c_dev {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
int mode;
|
||||
u16 tcr;
|
||||
int irq;
|
||||
u16 cmd_status;
|
||||
};
|
||||
@ -109,6 +106,12 @@ static int wmt_i2c_wait_bus_not_busy(struct wmt_i2c_dev *i2c_dev)
|
||||
static int wmt_check_status(struct wmt_i2c_dev *i2c_dev)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long wait_result;
|
||||
|
||||
wait_result = wait_for_completion_timeout(&i2c_dev->complete,
|
||||
msecs_to_jiffies(500));
|
||||
if (!wait_result)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
if (i2c_dev->cmd_status & ISR_NACK_ADDR)
|
||||
ret = -EIO;
|
||||
@ -119,21 +122,13 @@ static int wmt_check_status(struct wmt_i2c_dev *i2c_dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wmt_i2c_write(struct i2c_adapter *adap, struct i2c_msg *pmsg,
|
||||
static int wmt_i2c_write(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg,
|
||||
int last)
|
||||
{
|
||||
struct wmt_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
|
||||
u16 val, tcr_val;
|
||||
u16 val, tcr_val = i2c_dev->tcr;
|
||||
int ret;
|
||||
unsigned long wait_result;
|
||||
int xfer_len = 0;
|
||||
|
||||
if (!(pmsg->flags & I2C_M_NOSTART)) {
|
||||
ret = wmt_i2c_wait_bus_not_busy(i2c_dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pmsg->len == 0) {
|
||||
/*
|
||||
* We still need to run through the while (..) once, so
|
||||
@ -148,20 +143,12 @@ static int wmt_i2c_write(struct i2c_adapter *adap, struct i2c_msg *pmsg,
|
||||
if (!(pmsg->flags & I2C_M_NOSTART)) {
|
||||
val = readw(i2c_dev->base + REG_CR);
|
||||
val &= ~CR_TX_END;
|
||||
writew(val, i2c_dev->base + REG_CR);
|
||||
|
||||
val = readw(i2c_dev->base + REG_CR);
|
||||
val |= CR_CPU_RDY;
|
||||
writew(val, i2c_dev->base + REG_CR);
|
||||
}
|
||||
|
||||
reinit_completion(&i2c_dev->complete);
|
||||
|
||||
if (i2c_dev->mode == I2C_MODE_STANDARD)
|
||||
tcr_val = TCR_STANDARD_MODE;
|
||||
else
|
||||
tcr_val = TCR_FAST_MODE;
|
||||
|
||||
tcr_val |= (TCR_MASTER_WRITE | (pmsg->addr & TCR_SLAVE_ADDR_MASK));
|
||||
|
||||
writew(tcr_val, i2c_dev->base + REG_TCR);
|
||||
@ -173,12 +160,6 @@ static int wmt_i2c_write(struct i2c_adapter *adap, struct i2c_msg *pmsg,
|
||||
}
|
||||
|
||||
while (xfer_len < pmsg->len) {
|
||||
wait_result = wait_for_completion_timeout(&i2c_dev->complete,
|
||||
msecs_to_jiffies(500));
|
||||
|
||||
if (wait_result == 0)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
ret = wmt_check_status(i2c_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -210,48 +191,25 @@ static int wmt_i2c_write(struct i2c_adapter *adap, struct i2c_msg *pmsg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wmt_i2c_read(struct i2c_adapter *adap, struct i2c_msg *pmsg,
|
||||
int last)
|
||||
static int wmt_i2c_read(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg)
|
||||
{
|
||||
struct wmt_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
|
||||
u16 val, tcr_val;
|
||||
u16 val, tcr_val = i2c_dev->tcr;
|
||||
int ret;
|
||||
unsigned long wait_result;
|
||||
u32 xfer_len = 0;
|
||||
|
||||
if (!(pmsg->flags & I2C_M_NOSTART)) {
|
||||
ret = wmt_i2c_wait_bus_not_busy(i2c_dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
val = readw(i2c_dev->base + REG_CR);
|
||||
val &= ~CR_TX_END;
|
||||
writew(val, i2c_dev->base + REG_CR);
|
||||
val &= ~(CR_TX_END | CR_TX_NEXT_NO_ACK);
|
||||
|
||||
val = readw(i2c_dev->base + REG_CR);
|
||||
val &= ~CR_TX_NEXT_NO_ACK;
|
||||
writew(val, i2c_dev->base + REG_CR);
|
||||
|
||||
if (!(pmsg->flags & I2C_M_NOSTART)) {
|
||||
val = readw(i2c_dev->base + REG_CR);
|
||||
if (!(pmsg->flags & I2C_M_NOSTART))
|
||||
val |= CR_CPU_RDY;
|
||||
writew(val, i2c_dev->base + REG_CR);
|
||||
}
|
||||
|
||||
if (pmsg->len == 1) {
|
||||
val = readw(i2c_dev->base + REG_CR);
|
||||
if (pmsg->len == 1)
|
||||
val |= CR_TX_NEXT_NO_ACK;
|
||||
writew(val, i2c_dev->base + REG_CR);
|
||||
}
|
||||
|
||||
writew(val, i2c_dev->base + REG_CR);
|
||||
|
||||
reinit_completion(&i2c_dev->complete);
|
||||
|
||||
if (i2c_dev->mode == I2C_MODE_STANDARD)
|
||||
tcr_val = TCR_STANDARD_MODE;
|
||||
else
|
||||
tcr_val = TCR_FAST_MODE;
|
||||
|
||||
tcr_val |= TCR_MASTER_READ | (pmsg->addr & TCR_SLAVE_ADDR_MASK);
|
||||
|
||||
writew(tcr_val, i2c_dev->base + REG_TCR);
|
||||
@ -263,12 +221,6 @@ static int wmt_i2c_read(struct i2c_adapter *adap, struct i2c_msg *pmsg,
|
||||
}
|
||||
|
||||
while (xfer_len < pmsg->len) {
|
||||
wait_result = wait_for_completion_timeout(&i2c_dev->complete,
|
||||
msecs_to_jiffies(500));
|
||||
|
||||
if (!wait_result)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
ret = wmt_check_status(i2c_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -276,15 +228,10 @@ static int wmt_i2c_read(struct i2c_adapter *adap, struct i2c_msg *pmsg,
|
||||
pmsg->buf[xfer_len] = readw(i2c_dev->base + REG_CDR) >> 8;
|
||||
xfer_len++;
|
||||
|
||||
if (xfer_len == pmsg->len - 1) {
|
||||
val = readw(i2c_dev->base + REG_CR);
|
||||
val |= (CR_TX_NEXT_NO_ACK | CR_CPU_RDY);
|
||||
writew(val, i2c_dev->base + REG_CR);
|
||||
} else {
|
||||
val = readw(i2c_dev->base + REG_CR);
|
||||
val |= CR_CPU_RDY;
|
||||
writew(val, i2c_dev->base + REG_CR);
|
||||
}
|
||||
val = readw(i2c_dev->base + REG_CR) | CR_CPU_RDY;
|
||||
if (xfer_len == pmsg->len - 1)
|
||||
val |= CR_TX_NEXT_NO_ACK;
|
||||
writew(val, i2c_dev->base + REG_CR);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -295,17 +242,22 @@ static int wmt_i2c_xfer(struct i2c_adapter *adap,
|
||||
int num)
|
||||
{
|
||||
struct i2c_msg *pmsg;
|
||||
int i, is_last;
|
||||
int i;
|
||||
int ret = 0;
|
||||
struct wmt_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
|
||||
|
||||
for (i = 0; ret >= 0 && i < num; i++) {
|
||||
is_last = ((i + 1) == num);
|
||||
|
||||
pmsg = &msgs[i];
|
||||
if (!(pmsg->flags & I2C_M_NOSTART)) {
|
||||
ret = wmt_i2c_wait_bus_not_busy(i2c_dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pmsg->flags & I2C_M_RD)
|
||||
ret = wmt_i2c_read(adap, pmsg, is_last);
|
||||
ret = wmt_i2c_read(i2c_dev, pmsg);
|
||||
else
|
||||
ret = wmt_i2c_write(adap, pmsg, is_last);
|
||||
ret = wmt_i2c_write(i2c_dev, pmsg, (i + 1) == num);
|
||||
}
|
||||
|
||||
return (ret < 0) ? ret : i;
|
||||
@ -359,10 +311,10 @@ static int wmt_i2c_reset_hardware(struct wmt_i2c_dev *i2c_dev)
|
||||
readw(i2c_dev->base + REG_CSR); /* read clear */
|
||||
writew(ISR_WRITE_ALL, i2c_dev->base + REG_ISR);
|
||||
|
||||
if (i2c_dev->mode == I2C_MODE_STANDARD)
|
||||
writew(SCL_TIMEOUT(128) | TR_STD, i2c_dev->base + REG_TR);
|
||||
else
|
||||
if (i2c_dev->tcr == TCR_FAST_MODE)
|
||||
writew(SCL_TIMEOUT(128) | TR_HS, i2c_dev->base + REG_TR);
|
||||
else
|
||||
writew(SCL_TIMEOUT(128) | TR_STD, i2c_dev->base + REG_TR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -395,10 +347,9 @@ static int wmt_i2c_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(i2c_dev->clk);
|
||||
}
|
||||
|
||||
i2c_dev->mode = I2C_MODE_STANDARD;
|
||||
err = of_property_read_u32(np, "clock-frequency", &clk_rate);
|
||||
if (!err && (clk_rate == I2C_MAX_FAST_MODE_FREQ))
|
||||
i2c_dev->mode = I2C_MODE_FAST;
|
||||
i2c_dev->tcr = TCR_FAST_MODE;
|
||||
|
||||
i2c_dev->dev = &pdev->dev;
|
||||
|
||||
|
@ -427,7 +427,7 @@ static struct scx200_acb_iface *scx200_create_iface(const char *text,
|
||||
snprintf(adapter->name, sizeof(adapter->name), "%s ACB%d", text, index);
|
||||
adapter->owner = THIS_MODULE;
|
||||
adapter->algo = &scx200_acb_algorithm;
|
||||
adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
adapter->class = I2C_CLASS_HWMON;
|
||||
adapter->dev.parent = dev;
|
||||
|
||||
mutex_init(&iface->mutex);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/clk/clk-conf.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
@ -67,6 +68,8 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
|
||||
static DEFINE_STATIC_KEY_FALSE(i2c_trace_msg_key);
|
||||
static bool is_registered;
|
||||
|
||||
static struct dentry *i2c_debugfs_root;
|
||||
|
||||
int i2c_transfer_trace_reg(void)
|
||||
{
|
||||
static_branch_inc(&i2c_trace_msg_key);
|
||||
@ -689,7 +692,7 @@ static struct attribute *i2c_dev_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(i2c_dev);
|
||||
|
||||
struct bus_type i2c_bus_type = {
|
||||
const struct bus_type i2c_bus_type = {
|
||||
.name = "i2c",
|
||||
.match = i2c_device_match,
|
||||
.probe = i2c_device_probe,
|
||||
@ -1524,6 +1527,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
|
||||
goto out_list;
|
||||
}
|
||||
|
||||
adap->debugfs = debugfs_create_dir(dev_name(&adap->dev), i2c_debugfs_root);
|
||||
|
||||
res = i2c_setup_smbus_alert(adap);
|
||||
if (res)
|
||||
goto out_reg;
|
||||
@ -1563,6 +1568,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
|
||||
return 0;
|
||||
|
||||
out_reg:
|
||||
debugfs_remove_recursive(adap->debugfs);
|
||||
init_completion(&adap->dev_released);
|
||||
device_unregister(&adap->dev);
|
||||
wait_for_completion(&adap->dev_released);
|
||||
@ -1764,6 +1770,8 @@ void i2c_del_adapter(struct i2c_adapter *adap)
|
||||
|
||||
i2c_host_notify_irq_teardown(adap);
|
||||
|
||||
debugfs_remove_recursive(adap->debugfs);
|
||||
|
||||
/* wait until all references to the device are gone
|
||||
*
|
||||
* FIXME: This is old code and should ideally be replaced by an
|
||||
@ -2061,6 +2069,8 @@ static int __init i2c_init(void)
|
||||
|
||||
is_registered = true;
|
||||
|
||||
i2c_debugfs_root = debugfs_create_dir("i2c", NULL);
|
||||
|
||||
#ifdef CONFIG_I2C_COMPAT
|
||||
i2c_adapter_compat_class = class_compat_register("i2c-adapter");
|
||||
if (!i2c_adapter_compat_class) {
|
||||
@ -2099,6 +2109,7 @@ static void __exit i2c_exit(void)
|
||||
#ifdef CONFIG_I2C_COMPAT
|
||||
class_compat_unregister(i2c_adapter_compat_class);
|
||||
#endif
|
||||
debugfs_remove_recursive(i2c_debugfs_root);
|
||||
bus_unregister(&i2c_bus_type);
|
||||
tracepoint_synchronize_unregister();
|
||||
}
|
||||
|
@ -308,8 +308,8 @@ EXPORT_SYMBOL_GPL(i2c_free_slave_host_notify_device);
|
||||
* target systems are the same.
|
||||
* Restrictions to automatic SPD instantiation:
|
||||
* - Only works if all filled slots have the same memory type
|
||||
* - Only works for DDR2, DDR3 and DDR4 for now
|
||||
* - Only works on systems with 1 to 4 memory slots
|
||||
* - Only works for DDR, DDR2, DDR3 and DDR4 for now
|
||||
* - Only works on systems with 1 to 8 memory slots
|
||||
*/
|
||||
#if IS_ENABLED(CONFIG_DMI)
|
||||
void i2c_register_spd(struct i2c_adapter *adap)
|
||||
@ -354,9 +354,9 @@ void i2c_register_spd(struct i2c_adapter *adap)
|
||||
dev_info(&adap->dev, "%d/%d memory slots populated (from DMI)\n",
|
||||
dimm_count, slot_count);
|
||||
|
||||
if (slot_count > 4) {
|
||||
if (slot_count > 8) {
|
||||
dev_warn(&adap->dev,
|
||||
"Systems with more than 4 memory slots not supported yet, not instantiating SPD\n");
|
||||
"Systems with more than 8 memory slots not supported yet, not instantiating SPD\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -308,7 +308,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter stub_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
.name = "SMBus stub driver",
|
||||
};
|
||||
|
@ -159,7 +159,6 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
|
||||
struct regmux *mux;
|
||||
struct i2c_adapter *parent;
|
||||
struct resource *res;
|
||||
unsigned int class;
|
||||
int i, ret, nr;
|
||||
|
||||
mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
|
||||
@ -213,9 +212,8 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
|
||||
|
||||
for (i = 0; i < mux->data.n_values; i++) {
|
||||
nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
|
||||
class = mux->data.classes ? mux->data.classes[i] : 0;
|
||||
|
||||
ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
|
||||
ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], 0);
|
||||
if (ret)
|
||||
goto err_del_mux_adapters;
|
||||
}
|
||||
|
@ -289,7 +289,7 @@ static const struct i2c_algorithm netup_i2c_algorithm = {
|
||||
static const struct i2c_adapter netup_i2c_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = NETUP_UNIDVB_NAME,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &netup_i2c_algorithm,
|
||||
};
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/nvmem-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
@ -242,7 +243,7 @@ static const struct i2c_device_id at24_ids[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, at24_ids);
|
||||
|
||||
static const struct of_device_id at24_of_match[] = {
|
||||
static const struct of_device_id __maybe_unused at24_of_match[] = {
|
||||
{ .compatible = "atmel,24c00", .data = &at24_data_24c00 },
|
||||
{ .compatible = "atmel,24c01", .data = &at24_data_24c01 },
|
||||
{ .compatible = "atmel,24cs01", .data = &at24_data_24cs01 },
|
||||
@ -835,7 +836,7 @@ static struct i2c_driver at24_driver = {
|
||||
.driver = {
|
||||
.name = "at24",
|
||||
.pm = &at24_pm_ops,
|
||||
.of_match_table = at24_of_match,
|
||||
.of_match_table = of_match_ptr(at24_of_match),
|
||||
.acpi_match_table = ACPI_PTR(at24_acpi_ids),
|
||||
},
|
||||
.probe = at24_probe,
|
||||
|
@ -264,7 +264,7 @@ static int gb_i2c_probe(struct gbphy_device *gbphy_dev,
|
||||
/* Looks good; up our i2c adapter */
|
||||
adapter = &gb_i2c_dev->adapter;
|
||||
adapter->owner = THIS_MODULE;
|
||||
adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
adapter->class = I2C_CLASS_HWMON;
|
||||
adapter->algo = &gb_i2c_algorithm;
|
||||
|
||||
adapter->dev.parent = &gbphy_dev->dev;
|
||||
|
@ -116,7 +116,6 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter)
|
||||
algo_data->setsda(algo_data->data, 1);
|
||||
algo_data->setscl(algo_data->data, 1);
|
||||
|
||||
adapter->class |= I2C_CLASS_DDC;
|
||||
return edid;
|
||||
}
|
||||
|
||||
|
@ -1227,7 +1227,6 @@ static int cyber2000fb_setup_ddc_bus(struct cfb_info *cfb)
|
||||
strscpy(cfb->ddc_adapter.name, cfb->fb.fix.id,
|
||||
sizeof(cfb->ddc_adapter.name));
|
||||
cfb->ddc_adapter.owner = THIS_MODULE;
|
||||
cfb->ddc_adapter.class = I2C_CLASS_DDC;
|
||||
cfb->ddc_adapter.algo_data = &cfb->ddc_algo;
|
||||
cfb->ddc_adapter.dev.parent = cfb->fb.device;
|
||||
cfb->ddc_algo.setsda = cyber2000fb_ddc_setsda;
|
||||
|
@ -163,7 +163,6 @@ static int i740fb_setup_ddc_bus(struct fb_info *info)
|
||||
strscpy(par->ddc_adapter.name, info->fix.id,
|
||||
sizeof(par->ddc_adapter.name));
|
||||
par->ddc_adapter.owner = THIS_MODULE;
|
||||
par->ddc_adapter.class = I2C_CLASS_DDC;
|
||||
par->ddc_adapter.algo_data = &par->ddc_algo;
|
||||
par->ddc_adapter.dev.parent = info->device;
|
||||
par->ddc_algo.setsda = i740fb_ddc_setsda;
|
||||
|
@ -100,8 +100,7 @@ static const struct i2c_algo_bit_data matrox_i2c_algo_template =
|
||||
};
|
||||
|
||||
static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
|
||||
unsigned int data, unsigned int clock, const char *name,
|
||||
int class)
|
||||
unsigned int data, unsigned int clock, const char *name)
|
||||
{
|
||||
int err;
|
||||
|
||||
@ -112,7 +111,6 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
|
||||
snprintf(b->adapter.name, sizeof(b->adapter.name), name,
|
||||
minfo->fbcon.node);
|
||||
i2c_set_adapdata(&b->adapter, b);
|
||||
b->adapter.class = class;
|
||||
b->adapter.algo_data = &b->bac;
|
||||
b->adapter.dev.parent = &minfo->pcidev->dev;
|
||||
b->bac = matrox_i2c_algo_template;
|
||||
@ -160,27 +158,24 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
|
||||
case MGA_2164:
|
||||
err = i2c_bus_reg(&m2info->ddc1, minfo,
|
||||
DDC1B_DATA, DDC1B_CLK,
|
||||
"DDC:fb%u #0", I2C_CLASS_DDC);
|
||||
"DDC:fb%u #0");
|
||||
break;
|
||||
default:
|
||||
err = i2c_bus_reg(&m2info->ddc1, minfo,
|
||||
DDC1_DATA, DDC1_CLK,
|
||||
"DDC:fb%u #0", I2C_CLASS_DDC);
|
||||
"DDC:fb%u #0");
|
||||
break;
|
||||
}
|
||||
if (err)
|
||||
goto fail_ddc1;
|
||||
if (minfo->devflags.dualhead) {
|
||||
err = i2c_bus_reg(&m2info->ddc2, minfo,
|
||||
DDC2_DATA, DDC2_CLK,
|
||||
"DDC:fb%u #1", I2C_CLASS_DDC);
|
||||
err = i2c_bus_reg(&m2info->ddc2, minfo, DDC2_DATA, DDC2_CLK, "DDC:fb%u #1");
|
||||
if (err == -ENODEV) {
|
||||
printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n");
|
||||
} else if (err)
|
||||
printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n");
|
||||
/* Register maven bus even on G450/G550 */
|
||||
err = i2c_bus_reg(&m2info->maven, minfo,
|
||||
MAT_DATA, MAT_CLK, "MAVEN:fb%u", 0);
|
||||
err = i2c_bus_reg(&m2info->maven, minfo, MAT_DATA, MAT_CLK, "MAVEN:fb%u");
|
||||
if (err)
|
||||
printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n");
|
||||
else {
|
||||
|
@ -252,7 +252,6 @@ static int s3fb_setup_ddc_bus(struct fb_info *info)
|
||||
strscpy(par->ddc_adapter.name, info->fix.id,
|
||||
sizeof(par->ddc_adapter.name));
|
||||
par->ddc_adapter.owner = THIS_MODULE;
|
||||
par->ddc_adapter.class = I2C_CLASS_DDC;
|
||||
par->ddc_adapter.algo_data = &par->ddc_algo;
|
||||
par->ddc_adapter.dev.parent = info->device;
|
||||
par->ddc_algo.setsda = s3fb_ddc_setsda;
|
||||
|
@ -1267,7 +1267,6 @@ static int tdfxfb_setup_ddc_bus(struct tdfxfb_i2c_chan *chan, const char *name,
|
||||
|
||||
strscpy(chan->adapter.name, name, sizeof(chan->adapter.name));
|
||||
chan->adapter.owner = THIS_MODULE;
|
||||
chan->adapter.class = I2C_CLASS_DDC;
|
||||
chan->adapter.algo_data = &chan->algo;
|
||||
chan->adapter.dev.parent = dev;
|
||||
chan->algo.setsda = tdfxfb_ddc_setsda;
|
||||
|
@ -274,7 +274,6 @@ static int tridentfb_setup_ddc_bus(struct fb_info *info)
|
||||
strscpy(par->ddc_adapter.name, info->fix.id,
|
||||
sizeof(par->ddc_adapter.name));
|
||||
par->ddc_adapter.owner = THIS_MODULE;
|
||||
par->ddc_adapter.class = I2C_CLASS_DDC;
|
||||
par->ddc_adapter.algo_data = &par->ddc_algo;
|
||||
par->ddc_adapter.dev.parent = info->device;
|
||||
if (is_oldclock(par->chip_id)) { /* not sure if this check is OK */
|
||||
|
@ -201,7 +201,6 @@ static int create_i2c_bus(struct i2c_adapter *adapter,
|
||||
sprintf(adapter->name, "viafb i2c io_port idx 0x%02x",
|
||||
adap_cfg->ioport_index);
|
||||
adapter->owner = THIS_MODULE;
|
||||
adapter->class = I2C_CLASS_DDC;
|
||||
adapter->algo_data = algo;
|
||||
if (pdev)
|
||||
adapter->dev.parent = &pdev->dev;
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <linux/swab.h> /* for swab16 */
|
||||
#include <uapi/linux/i2c.h>
|
||||
|
||||
extern struct bus_type i2c_bus_type;
|
||||
extern const struct bus_type i2c_bus_type;
|
||||
extern struct device_type i2c_adapter_type;
|
||||
extern struct device_type i2c_client_type;
|
||||
|
||||
@ -746,6 +746,8 @@ struct i2c_adapter {
|
||||
|
||||
struct irq_domain *host_notify_domain;
|
||||
struct regulator *bus_regulator;
|
||||
|
||||
struct dentry *debugfs;
|
||||
};
|
||||
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
|
||||
|
||||
@ -850,7 +852,6 @@ static inline void i2c_mark_adapter_resumed(struct i2c_adapter *adap)
|
||||
|
||||
/* i2c adapter classes (bitmask) */
|
||||
#define I2C_CLASS_HWMON (1<<0) /* lm_sensors, ... */
|
||||
#define I2C_CLASS_DDC (1<<3) /* DDC bus on graphics adapters */
|
||||
#define I2C_CLASS_SPD (1<<7) /* Memory modules */
|
||||
/* Warn users that the adapter doesn't support classes anymore */
|
||||
#define I2C_CLASS_DEPRECATED (1<<8)
|
||||
|
@ -17,7 +17,6 @@
|
||||
* @n_values: Number of multiplexer channels
|
||||
* @little_endian: Indicating if the register is in little endian
|
||||
* @write_only: Reading the register is not allowed by hardware
|
||||
* @classes: Optional I2C auto-detection classes
|
||||
* @idle: Value to write to mux when idle
|
||||
* @idle_in_use: indicate if idle value is in use
|
||||
* @reg: Virtual address of the register to switch channel
|
||||
@ -30,7 +29,6 @@ struct i2c_mux_reg_platform_data {
|
||||
int n_values;
|
||||
bool little_endian;
|
||||
bool write_only;
|
||||
const unsigned int *classes;
|
||||
u32 idle;
|
||||
bool idle_in_use;
|
||||
void __iomem *reg;
|
||||
|
@ -446,7 +446,7 @@ static const struct rockchip_sound_route rockchip_routes[] = {
|
||||
|
||||
struct dailink_match_data {
|
||||
const char *compatible;
|
||||
struct bus_type *bus_type;
|
||||
const struct bus_type *bus_type;
|
||||
};
|
||||
|
||||
static const struct dailink_match_data dailink_match[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user