1
0
Fork 0

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>
hifive-unleashed-5.1
Jan Glauber 2016-08-24 23:25:45 +02:00 committed by Wolfram Sang
parent 22d40209de
commit 1e5866711a
3 changed files with 50 additions and 0 deletions

View File

@ -959,6 +959,7 @@ config I2C_OCTEON
config I2C_THUNDERX config I2C_THUNDERX
tristate "Cavium ThunderX I2C bus support" tristate "Cavium ThunderX I2C bus support"
depends on 64BIT && PCI && (ARM64 || COMPILE_TEST) depends on 64BIT && PCI && (ARM64 || COMPILE_TEST)
select I2C_SMBUS
help help
Say yes if you want to support the I2C serial bus on Cavium Say yes if you want to support the I2C serial bus on Cavium
ThunderX SOC. ThunderX SOC.

View File

@ -3,6 +3,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/pci.h> #include <linux/pci.h>
@ -119,6 +120,8 @@ struct octeon_i2c {
#if IS_ENABLED(CONFIG_I2C_THUNDERX) #if IS_ENABLED(CONFIG_I2C_THUNDERX)
struct msix_entry i2c_msix; struct msix_entry i2c_msix;
#endif #endif
struct i2c_smbus_alert_setup alert_data;
struct i2c_client *ara;
}; };
static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr) static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr)

View File

@ -14,9 +14,11 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/pci.h> #include <linux/pci.h>
#include "i2c-octeon-core.h" #include "i2c-octeon-core.h"
@ -107,6 +109,44 @@ static void thunder_i2c_clock_disable(struct device *dev, struct clk *clk)
clk_put(clk); clk_put(clk);
} }
static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c,
struct device_node *node)
{
u32 type;
if (!node)
return -EINVAL;
i2c->alert_data.irq = irq_of_parse_and_map(node, 0);
if (!i2c->alert_data.irq)
return -EINVAL;
type = irqd_get_trigger_type(irq_get_irq_data(i2c->alert_data.irq));
i2c->alert_data.alert_edge_triggered =
(type & IRQ_TYPE_LEVEL_MASK) ? 1 : 0;
i2c->ara = i2c_setup_smbus_alert(&i2c->adap, &i2c->alert_data);
if (!i2c->ara)
return -ENODEV;
return 0;
}
static int thunder_i2c_smbus_setup(struct octeon_i2c *i2c,
struct device_node *node)
{
/* TODO: ACPI support */
if (!acpi_disabled)
return -EOPNOTSUPP;
return thunder_i2c_smbus_setup_of(i2c, node);
}
static void thunder_i2c_smbus_remove(struct octeon_i2c *i2c)
{
if (i2c->ara)
i2c_unregister_device(i2c->ara);
}
static int thunder_i2c_probe_pci(struct pci_dev *pdev, static int thunder_i2c_probe_pci(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
@ -173,6 +213,11 @@ static int thunder_i2c_probe_pci(struct pci_dev *pdev,
goto error; goto error;
dev_info(i2c->dev, "Probed. Set system clock to %u\n", i2c->sys_freq); dev_info(i2c->dev, "Probed. Set system clock to %u\n", i2c->sys_freq);
ret = thunder_i2c_smbus_setup(i2c, pdev->dev.of_node);
if (ret)
dev_info(dev, "SMBUS alert not active on this bus\n");
return 0; return 0;
error: error:
@ -184,6 +229,7 @@ static void thunder_i2c_remove_pci(struct pci_dev *pdev)
{ {
struct octeon_i2c *i2c = pci_get_drvdata(pdev); struct octeon_i2c *i2c = pci_get_drvdata(pdev);
thunder_i2c_smbus_remove(i2c);
thunder_i2c_clock_disable(&pdev->dev, i2c->clk); thunder_i2c_clock_disable(&pdev->dev, i2c->clk);
i2c_del_adapter(&i2c->adap); i2c_del_adapter(&i2c->adap);
} }