* - Make it work with IXP46x chips
* - Cleanup function names, coding style, etc
*
+ * - writing to slave address causes latchup on iop331.
+ * fix: driver refuses to address self.
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*/
-#include <linux/config.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
__raw_writel(0, iop3xx_adap->ioaddr + CR_OFFSET);
}
-static void
-iop3xx_i2c_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap)
-{
- __raw_writel(MYSAR, iop3xx_adap->ioaddr + SAR_OFFSET);
-}
-
static void
iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
/*
* Every time unit enable is asserted, GPOD needs to be cleared
- * on IOP321 to avoid data corruption on the bus.
+ * on IOP3XX to avoid data corruption on the bus.
*/
-#ifdef CONFIG_ARCH_IOP321
-#define IOP321_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */
-#define IOP321_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */
-
- *IOP321_GPOD &= (iop3xx_adap->id == 0) ? ~IOP321_GPOD_I2C0 :
- ~IOP321_GPOD_I2C1;
+#ifdef CONFIG_PLAT_IOP
+ if (iop3xx_adap->id == 0) {
+ gpio_line_set(IOP3XX_GPIO_LINE(7), GPIO_LOW);
+ gpio_line_set(IOP3XX_GPIO_LINE(6), GPIO_LOW);
+ } else {
+ gpio_line_set(IOP3XX_GPIO_LINE(5), GPIO_LOW);
+ gpio_line_set(IOP3XX_GPIO_LINE(4), GPIO_LOW);
+ }
#endif
/* NB SR bits not same position as CR IE bits :-( */
iop3xx_adap->SR_enabled =
int status;
int rc;
+ /* avoid writing to my slave address (hangs on 80331),
+ * forbidden in Intel developer manual
+ */
+ if (msg->addr == MYSAR) {
+ return -EBUSY;
+ }
+
__raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET);
cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
};
static int
-iop3xx_i2c_remove(struct device *device)
+iop3xx_i2c_remove(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(device);
- struct i2c_adapter *padapter = dev_get_drvdata(&pdev->dev);
+ struct i2c_adapter *padapter = platform_get_drvdata(pdev);
struct i2c_algo_iop3xx_data *adapter_data =
(struct i2c_algo_iop3xx_data *)padapter->algo_data;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
kfree(adapter_data);
kfree(padapter);
- dev_set_drvdata(&pdev->dev, NULL);
+ platform_set_drvdata(pdev, NULL);
return 0;
}
static int
-iop3xx_i2c_probe(struct device *dev)
+iop3xx_i2c_probe(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(dev);
struct resource *res;
- int ret;
+ int ret, irq;
struct i2c_adapter *new_adapter;
struct i2c_algo_iop3xx_data *adapter_data;
goto release_region;
}
- ret = request_irq(platform_get_irq(pdev, 0), iop3xx_i2c_irq_handler, 0,
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = -ENXIO;
+ goto unmap;
+ }
+ ret = request_irq(irq, iop3xx_i2c_irq_handler, 0,
pdev->name, adapter_data);
if (ret) {
spin_lock_init(&adapter_data->lock);
iop3xx_i2c_reset(adapter_data);
- iop3xx_i2c_set_slave_addr(adapter_data);
iop3xx_i2c_enable(adapter_data);
- dev_set_drvdata(&pdev->dev, new_adapter);
+ platform_set_drvdata(pdev, new_adapter);
new_adapter->algo_data = adapter_data;
i2c_add_adapter(new_adapter);
}
-static struct device_driver iop3xx_i2c_driver = {
- .owner = THIS_MODULE,
- .name = "IOP3xx-I2C",
- .bus = &platform_bus_type,
+static struct platform_driver iop3xx_i2c_driver = {
.probe = iop3xx_i2c_probe,
- .remove = iop3xx_i2c_remove
+ .remove = iop3xx_i2c_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "IOP3xx-I2C",
+ },
};
static int __init
i2c_iop3xx_init (void)
{
- return driver_register(&iop3xx_i2c_driver);
+ return platform_driver_register(&iop3xx_i2c_driver);
}
static void __exit
i2c_iop3xx_exit (void)
{
- driver_unregister(&iop3xx_i2c_driver);
+ platform_driver_unregister(&iop3xx_i2c_driver);
return;
}