diff options
author | Jan Glauber <jglauber@cavium.com> | 2016-08-24 17:25:45 -0400 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2016-08-25 18:41:56 -0400 |
commit | 1e5866711accf16e931c4f8174cf898b554e9f4a (patch) | |
tree | 35afb3ecfc00e397b4260d2fd89318e8ff8c8ff8 | |
parent | 22d40209de3bb50cbffcc6b79f2f7c5d689d185f (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/Kconfig | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-octeon-core.h | 3 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-thunderx-pcidrv.c | 46 |
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 | |||
959 | config I2C_THUNDERX | 959 | config 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 | ||
124 | static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr) | 127 | static 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 | ||
112 | static 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 | |||
134 | static 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 | |||
144 | static void thunder_i2c_smbus_remove(struct octeon_i2c *i2c) | ||
145 | { | ||
146 | if (i2c->ara) | ||
147 | i2c_unregister_device(i2c->ara); | ||
148 | } | ||
149 | |||
110 | static int thunder_i2c_probe_pci(struct pci_dev *pdev, | 150 | static 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 | ||
178 | error: | 223 | error: |
@@ -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 | } |