aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Glauber <jglauber@cavium.com>2016-08-24 17:25:45 -0400
committerWolfram Sang <wsa@the-dreams.de>2016-08-25 18:41:56 -0400
commit1e5866711accf16e931c4f8174cf898b554e9f4a (patch)
tree35afb3ecfc00e397b4260d2fd89318e8ff8c8ff8
parent22d40209de3bb50cbffcc6b79f2f7c5d689d185f (diff)
i2c: thunderx: Add SMBUS alert support
Add SMBUS alert interrupt support. For now only device tree is supported for specifying the alert. In case of ACPI an error is returned. Signed-off-by: Jan Glauber <jglauber@cavium.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r--drivers/i2c/busses/Kconfig1
-rw-r--r--drivers/i2c/busses/i2c-octeon-core.h3
-rw-r--r--drivers/i2c/busses/i2c-thunderx-pcidrv.c46
3 files changed, 50 insertions, 0 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d69a3420c8dc..1f3239ead037 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -959,6 +959,7 @@ config I2C_OCTEON
959config I2C_THUNDERX 959config I2C_THUNDERX
960 tristate "Cavium ThunderX I2C bus support" 960 tristate "Cavium ThunderX I2C bus support"
961 depends on 64BIT && PCI && (ARM64 || COMPILE_TEST) 961 depends on 64BIT && PCI && (ARM64 || COMPILE_TEST)
962 select I2C_SMBUS
962 help 963 help
963 Say yes if you want to support the I2C serial bus on Cavium 964 Say yes if you want to support the I2C serial bus on Cavium
964 ThunderX SOC. 965 ThunderX SOC.
diff --git a/drivers/i2c/busses/i2c-octeon-core.h b/drivers/i2c/busses/i2c-octeon-core.h
index 33c7e1fb178c..2ed6f7a36b88 100644
--- a/drivers/i2c/busses/i2c-octeon-core.h
+++ b/drivers/i2c/busses/i2c-octeon-core.h
@@ -3,6 +3,7 @@
3#include <linux/delay.h> 3#include <linux/delay.h>
4#include <linux/device.h> 4#include <linux/device.h>
5#include <linux/i2c.h> 5#include <linux/i2c.h>
6#include <linux/i2c-smbus.h>
6#include <linux/io.h> 7#include <linux/io.h>
7#include <linux/kernel.h> 8#include <linux/kernel.h>
8#include <linux/pci.h> 9#include <linux/pci.h>
@@ -119,6 +120,8 @@ struct octeon_i2c {
119#if IS_ENABLED(CONFIG_I2C_THUNDERX) 120#if IS_ENABLED(CONFIG_I2C_THUNDERX)
120 struct msix_entry i2c_msix; 121 struct msix_entry i2c_msix;
121#endif 122#endif
123 struct i2c_smbus_alert_setup alert_data;
124 struct i2c_client *ara;
122}; 125};
123 126
124static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr) 127static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr)
diff --git a/drivers/i2c/busses/i2c-thunderx-pcidrv.c b/drivers/i2c/busses/i2c-thunderx-pcidrv.c
index 0dcebe2a5c4f..e8c3ce0eaf4d 100644
--- a/drivers/i2c/busses/i2c-thunderx-pcidrv.c
+++ b/drivers/i2c/busses/i2c-thunderx-pcidrv.c
@@ -14,9 +14,11 @@
14#include <linux/clk.h> 14#include <linux/clk.h>
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/i2c.h> 16#include <linux/i2c.h>
17#include <linux/i2c-smbus.h>
17#include <linux/interrupt.h> 18#include <linux/interrupt.h>
18#include <linux/kernel.h> 19#include <linux/kernel.h>
19#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/of_irq.h>
20#include <linux/pci.h> 22#include <linux/pci.h>
21 23
22#include "i2c-octeon-core.h" 24#include "i2c-octeon-core.h"
@@ -107,6 +109,44 @@ static void thunder_i2c_clock_disable(struct device *dev, struct clk *clk)
107 clk_put(clk); 109 clk_put(clk);
108} 110}
109 111
112static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c,
113 struct device_node *node)
114{
115 u32 type;
116
117 if (!node)
118 return -EINVAL;
119
120 i2c->alert_data.irq = irq_of_parse_and_map(node, 0);
121 if (!i2c->alert_data.irq)
122 return -EINVAL;
123
124 type = irqd_get_trigger_type(irq_get_irq_data(i2c->alert_data.irq));
125 i2c->alert_data.alert_edge_triggered =
126 (type & IRQ_TYPE_LEVEL_MASK) ? 1 : 0;
127
128 i2c->ara = i2c_setup_smbus_alert(&i2c->adap, &i2c->alert_data);
129 if (!i2c->ara)
130 return -ENODEV;
131 return 0;
132}
133
134static int thunder_i2c_smbus_setup(struct octeon_i2c *i2c,
135 struct device_node *node)
136{
137 /* TODO: ACPI support */
138 if (!acpi_disabled)
139 return -EOPNOTSUPP;
140
141 return thunder_i2c_smbus_setup_of(i2c, node);
142}
143
144static void thunder_i2c_smbus_remove(struct octeon_i2c *i2c)
145{
146 if (i2c->ara)
147 i2c_unregister_device(i2c->ara);
148}
149
110static int thunder_i2c_probe_pci(struct pci_dev *pdev, 150static int thunder_i2c_probe_pci(struct pci_dev *pdev,
111 const struct pci_device_id *ent) 151 const struct pci_device_id *ent)
112{ 152{
@@ -173,6 +213,11 @@ static int thunder_i2c_probe_pci(struct pci_dev *pdev,
173 goto error; 213 goto error;
174 214
175 dev_info(i2c->dev, "Probed. Set system clock to %u\n", i2c->sys_freq); 215 dev_info(i2c->dev, "Probed. Set system clock to %u\n", i2c->sys_freq);
216
217 ret = thunder_i2c_smbus_setup(i2c, pdev->dev.of_node);
218 if (ret)
219 dev_info(dev, "SMBUS alert not active on this bus\n");
220
176 return 0; 221 return 0;
177 222
178error: 223error:
@@ -184,6 +229,7 @@ static void thunder_i2c_remove_pci(struct pci_dev *pdev)
184{ 229{
185 struct octeon_i2c *i2c = pci_get_drvdata(pdev); 230 struct octeon_i2c *i2c = pci_get_drvdata(pdev);
186 231
232 thunder_i2c_smbus_remove(i2c);
187 thunder_i2c_clock_disable(&pdev->dev, i2c->clk); 233 thunder_i2c_clock_disable(&pdev->dev, i2c->clk);
188 i2c_del_adapter(&i2c->adap); 234 i2c_del_adapter(&i2c->adap);
189} 235}