diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-01-07 11:03:49 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-01-07 11:03:49 +1100 |
commit | a0b1fcf2f2343fc63fcfa847a0a9d333d4da752b (patch) | |
tree | 0e808e5823fa4d0f3736e2736cbbc1e8d8482c9d /drivers | |
parent | 6ad918b99c7085f21ee6e65f7bc6713ad800c737 (diff) | |
parent | 3dc12a99449fa9aa7fe3d146874f24f01a716c9d (diff) |
Merge remote branch 'arm/devel'
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/i2c/busses/i2c-pnx.c | 285 | ||||
-rw-r--r-- | drivers/watchdog/pnx4008_wdt.c | 39 |
2 files changed, 180 insertions, 144 deletions
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 5d1c2603a130..e480fa0d7d4d 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -20,15 +20,15 @@ #include <linux/platform_device.h> #include <linux/i2c-pnx.h> #include <linux/io.h> +#include <linux/err.h> +#include <linux/clk.h> + #include <mach/hardware.h> #include <mach/i2c.h> -#include <asm/irq.h> -#include <asm/uaccess.h> #define I2C_PNX_TIMEOUT 10 /* msec */ #define I2C_PNX_SPEED_KHZ 100 #define I2C_PNX_REGION_SIZE 0x100 -#define PNX_DEFAULT_FREQ 13 /* MHz */ static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data) { @@ -50,22 +50,21 @@ static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data) return (timeout <= 0); } -static inline void i2c_pnx_arm_timer(struct i2c_adapter *adap) +static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data) { - struct i2c_pnx_algo_data *data = adap->algo_data; - struct timer_list *timer = &data->mif.timer; - int expires = I2C_PNX_TIMEOUT / (1000 / HZ); + struct timer_list *timer = &alg_data->mif.timer; + unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT); if (expires <= 1) expires = 2; del_timer_sync(timer); - dev_dbg(&adap->dev, "Timer armed at %lu plus %u jiffies.\n", + dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %lu jiffies.\n", jiffies, expires); timer->expires = jiffies + expires; - timer->data = (unsigned long)adap; + timer->data = (unsigned long)&alg_data; add_timer(timer); } @@ -77,34 +76,34 @@ static inline void i2c_pnx_arm_timer(struct i2c_adapter *adap) * * Generate a START signal in the desired mode. */ -static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap) +static int i2c_pnx_start(unsigned char slave_addr, + struct i2c_pnx_algo_data *alg_data) { - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - - dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __func__, + dev_dbg(&alg_data->adapter.dev, "%s(): addr 0x%x mode %d\n", __func__, slave_addr, alg_data->mif.mode); /* Check for 7 bit slave addresses only */ if (slave_addr & ~0x7f) { - dev_err(&adap->dev, "%s: Invalid slave address %x. " - "Only 7-bit addresses are supported\n", - adap->name, slave_addr); + dev_err(&alg_data->adapter.dev, + "%s: Invalid slave address %x. Only 7-bit addresses are supported\n", + alg_data->adapter.name, slave_addr); return -EINVAL; } /* First, make sure bus is idle */ if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) { /* Somebody else is monopolizing the bus */ - dev_err(&adap->dev, "%s: Bus busy. Slave addr = %02x, " - "cntrl = %x, stat = %x\n", - adap->name, slave_addr, - ioread32(I2C_REG_CTL(alg_data)), - ioread32(I2C_REG_STS(alg_data))); + dev_err(&alg_data->adapter.dev, + "%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n", + alg_data->adapter.name, slave_addr, + ioread32(I2C_REG_CTL(alg_data)), + ioread32(I2C_REG_STS(alg_data))); return -EBUSY; } else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) { /* Sorry, we lost the bus */ - dev_err(&adap->dev, "%s: Arbitration failure. " - "Slave addr = %02x\n", adap->name, slave_addr); + dev_err(&alg_data->adapter.dev, + "%s: Arbitration failure. Slave addr = %02x\n", + alg_data->adapter.name, slave_addr); return -EIO; } @@ -115,14 +114,14 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap) iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data)); - dev_dbg(&adap->dev, "%s(): sending %#x\n", __func__, + dev_dbg(&alg_data->adapter.dev, "%s(): sending %#x\n", __func__, (slave_addr << 1) | start_bit | alg_data->mif.mode); /* Write the slave address, START bit and R/W bit */ iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode, I2C_REG_TX(alg_data)); - dev_dbg(&adap->dev, "%s(): exit\n", __func__); + dev_dbg(&alg_data->adapter.dev, "%s(): exit\n", __func__); return 0; } @@ -133,13 +132,12 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap) * * Generate a STOP signal to terminate the master transaction. */ -static void i2c_pnx_stop(struct i2c_adapter *adap) +static void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data) { - struct i2c_pnx_algo_data *alg_data = adap->algo_data; /* Only 1 msec max timeout due to interrupt context */ long timeout = 1000; - dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n", __func__, ioread32(I2C_REG_STS(alg_data))); /* Write a STOP bit to TX FIFO */ @@ -153,7 +151,7 @@ static void i2c_pnx_stop(struct i2c_adapter *adap) timeout--; } - dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n", __func__, ioread32(I2C_REG_STS(alg_data))); } @@ -163,12 +161,11 @@ static void i2c_pnx_stop(struct i2c_adapter *adap) * * Sends one byte of data to the slave */ -static int i2c_pnx_master_xmit(struct i2c_adapter *adap) +static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data) { - struct i2c_pnx_algo_data *alg_data = adap->algo_data; u32 val; - dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n", __func__, ioread32(I2C_REG_STS(alg_data))); if (alg_data->mif.len > 0) { @@ -184,15 +181,15 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap) alg_data->mif.len--; iowrite32(val, I2C_REG_TX(alg_data)); - dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __func__, - val, alg_data->mif.len + 1); + dev_dbg(&alg_data->adapter.dev, "%s(): xmit %#x [%d]\n", + __func__, val, alg_data->mif.len + 1); if (alg_data->mif.len == 0) { if (alg_data->last) { /* Wait until the STOP is seen. */ if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) - dev_err(&adap->dev, "The bus is still " - "active after timeout\n"); + dev_err(&alg_data->adapter.dev, + "The bus is still active after timeout\n"); } /* Disable master interrupts */ iowrite32(ioread32(I2C_REG_CTL(alg_data)) & @@ -201,14 +198,15 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap) del_timer_sync(&alg_data->mif.timer); - dev_dbg(&adap->dev, "%s(): Waking up xfer routine.\n", + dev_dbg(&alg_data->adapter.dev, + "%s(): Waking up xfer routine.\n", __func__); complete(&alg_data->mif.complete); } } else if (alg_data->mif.len == 0) { /* zero-sized transfer */ - i2c_pnx_stop(adap); + i2c_pnx_stop(alg_data); /* Disable master interrupts. */ iowrite32(ioread32(I2C_REG_CTL(alg_data)) & @@ -217,13 +215,14 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap) /* Stop timer. */ del_timer_sync(&alg_data->mif.timer); - dev_dbg(&adap->dev, "%s(): Waking up xfer routine after " - "zero-xfer.\n", __func__); + dev_dbg(&alg_data->adapter.dev, + "%s(): Waking up xfer routine after zero-xfer.\n", + __func__); complete(&alg_data->mif.complete); } - dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n", __func__, ioread32(I2C_REG_STS(alg_data))); return 0; @@ -235,21 +234,21 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap) * * Reads one byte data from the slave */ -static int i2c_pnx_master_rcv(struct i2c_adapter *adap) +static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data) { - struct i2c_pnx_algo_data *alg_data = adap->algo_data; unsigned int val = 0; u32 ctl = 0; - dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n", __func__, ioread32(I2C_REG_STS(alg_data))); /* Check, whether there is already data, * or we didn't 'ask' for it yet. */ if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) { - dev_dbg(&adap->dev, "%s(): Write dummy data to fill " - "Rx-fifo...\n", __func__); + dev_dbg(&alg_data->adapter.dev, + "%s(): Write dummy data to fill Rx-fifo...\n", + __func__); if (alg_data->mif.len == 1) { /* Last byte, do not acknowledge next rcv. */ @@ -281,16 +280,16 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap) if (alg_data->mif.len > 0) { val = ioread32(I2C_REG_RX(alg_data)); *alg_data->mif.buf++ = (u8) (val & 0xff); - dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __func__, val, - alg_data->mif.len); + dev_dbg(&alg_data->adapter.dev, "%s(): rcv 0x%x [%d]\n", + __func__, val, alg_data->mif.len); alg_data->mif.len--; if (alg_data->mif.len == 0) { if (alg_data->last) /* Wait until the STOP is seen. */ if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) - dev_err(&adap->dev, "The bus is still " - "active after timeout\n"); + dev_err(&alg_data->adapter.dev, + "The bus is still active after timeout\n"); /* Disable master interrupts */ ctl = ioread32(I2C_REG_CTL(alg_data)); @@ -304,7 +303,7 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap) } } - dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n", __func__, ioread32(I2C_REG_STS(alg_data))); return 0; @@ -312,11 +311,11 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap) static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id) { + struct i2c_pnx_algo_data *alg_data = dev_id; u32 stat, ctl; - struct i2c_adapter *adap = dev_id; - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - dev_dbg(&adap->dev, "%s(): mstat = %x mctrl = %x, mode = %d\n", + dev_dbg(&alg_data->adapter.dev, + "%s(): mstat = %x mctrl = %x, mode = %d\n", __func__, ioread32(I2C_REG_STS(alg_data)), ioread32(I2C_REG_CTL(alg_data)), @@ -339,10 +338,10 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id) complete(&alg_data->mif.complete); } else if (stat & mstatus_nai) { /* Slave did not acknowledge, generate a STOP */ - dev_dbg(&adap->dev, "%s(): " - "Slave did not acknowledge, generating a STOP.\n", + dev_dbg(&alg_data->adapter.dev, + "%s(): Slave did not acknowledge, generating a STOP.\n", __func__); - i2c_pnx_stop(adap); + i2c_pnx_stop(alg_data); /* Disable master interrupts. */ ctl = ioread32(I2C_REG_CTL(alg_data)); @@ -368,9 +367,9 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id) */ if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) { if (alg_data->mif.mode == I2C_SMBUS_WRITE) { - i2c_pnx_master_xmit(adap); + i2c_pnx_master_xmit(alg_data); } else if (alg_data->mif.mode == I2C_SMBUS_READ) { - i2c_pnx_master_rcv(adap); + i2c_pnx_master_rcv(alg_data); } } } @@ -379,7 +378,8 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id) stat = ioread32(I2C_REG_STS(alg_data)); iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data)); - dev_dbg(&adap->dev, "%s(): exiting, stat = %x ctrl = %x.\n", + dev_dbg(&alg_data->adapter.dev, + "%s(): exiting, stat = %x ctrl = %x.\n", __func__, ioread32(I2C_REG_STS(alg_data)), ioread32(I2C_REG_CTL(alg_data))); @@ -388,14 +388,13 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id) static void i2c_pnx_timeout(unsigned long data) { - struct i2c_adapter *adap = (struct i2c_adapter *)data; - struct i2c_pnx_algo_data *alg_data = adap->algo_data; + struct i2c_pnx_algo_data *alg_data = (struct i2c_pnx_algo_data *)data; u32 ctl; - dev_err(&adap->dev, "Master timed out. stat = %04x, cntrl = %04x. " - "Resetting master...\n", - ioread32(I2C_REG_STS(alg_data)), - ioread32(I2C_REG_CTL(alg_data))); + dev_err(&alg_data->adapter.dev, + "Master timed out. stat = %04x, cntrl = %04x. Resetting master...\n", + ioread32(I2C_REG_STS(alg_data)), + ioread32(I2C_REG_CTL(alg_data))); /* Reset master and disable interrupts */ ctl = ioread32(I2C_REG_CTL(alg_data)); @@ -409,15 +408,14 @@ static void i2c_pnx_timeout(unsigned long data) complete(&alg_data->mif.complete); } -static inline void bus_reset_if_active(struct i2c_adapter *adap) +static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data) { - struct i2c_pnx_algo_data *alg_data = adap->algo_data; u32 stat; if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) { - dev_err(&adap->dev, + dev_err(&alg_data->adapter.dev, "%s: Bus is still active after xfer. Reset it...\n", - adap->name); + alg_data->adapter.name); iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, I2C_REG_CTL(alg_data)); wait_reset(I2C_PNX_TIMEOUT, alg_data); @@ -451,10 +449,11 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) struct i2c_pnx_algo_data *alg_data = adap->algo_data; u32 stat = ioread32(I2C_REG_STS(alg_data)); - dev_dbg(&adap->dev, "%s(): entering: %d messages, stat = %04x.\n", + dev_dbg(&alg_data->adapter.dev, + "%s(): entering: %d messages, stat = %04x.\n", __func__, num, ioread32(I2C_REG_STS(alg_data))); - bus_reset_if_active(adap); + bus_reset_if_active(alg_data); /* Process transactions in a loop. */ for (i = 0; rc >= 0 && i < num; i++) { @@ -464,9 +463,9 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) addr = pmsg->addr; if (pmsg->flags & I2C_M_TEN) { - dev_err(&adap->dev, + dev_err(&alg_data->adapter.dev, "%s: 10 bits addr not supported!\n", - adap->name); + alg_data->adapter.name); rc = -EINVAL; break; } @@ -478,11 +477,10 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) alg_data->mif.ret = 0; alg_data->last = (i == num - 1); - dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __func__, - alg_data->mif.mode, - alg_data->mif.len); + dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n", + __func__, alg_data->mif.mode, alg_data->mif.len); - i2c_pnx_arm_timer(adap); + i2c_pnx_arm_timer(alg_data); /* initialize the completion var */ init_completion(&alg_data->mif.complete); @@ -493,7 +491,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) I2C_REG_CTL(alg_data)); /* Put start-code and slave-address on the bus. */ - rc = i2c_pnx_start(addr, adap); + rc = i2c_pnx_start(addr, alg_data); if (rc < 0) break; @@ -502,31 +500,32 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if (!(rc = alg_data->mif.ret)) completed++; - dev_dbg(&adap->dev, "%s(): Complete, return code = %d.\n", + dev_dbg(&alg_data->adapter.dev, + "%s(): Complete, return code = %d.\n", __func__, rc); /* Clear TDI and AFI bits in case they are set. */ if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) { - dev_dbg(&adap->dev, + dev_dbg(&alg_data->adapter.dev, "%s: TDI still set... clearing now.\n", - adap->name); + alg_data->adapter.name); iowrite32(stat, I2C_REG_STS(alg_data)); } if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) { - dev_dbg(&adap->dev, + dev_dbg(&alg_data->adapter.dev, "%s: AFI still set... clearing now.\n", - adap->name); + alg_data->adapter.name); iowrite32(stat, I2C_REG_STS(alg_data)); } } - bus_reset_if_active(adap); + bus_reset_if_active(alg_data); /* Cleanup to be sure... */ alg_data->mif.buf = NULL; alg_data->mif.len = 0; - dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n", + dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n", __func__, ioread32(I2C_REG_STS(alg_data))); if (completed != num) @@ -545,69 +544,92 @@ static struct i2c_algorithm pnx_algorithm = { .functionality = i2c_pnx_func, }; +#ifdef CONFIG_PM static int i2c_pnx_controller_suspend(struct platform_device *pdev, pm_message_t state) { - struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); - return i2c_pnx->suspend(pdev, state); + struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); + + /* FIXME: shouldn't this be clk_disable? */ + clk_enable(alg_data->clk); + + return 0; } static int i2c_pnx_controller_resume(struct platform_device *pdev) { - struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); - return i2c_pnx->resume(pdev); + struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); + + return clk_enable(alg_data->clk); } +#else +#define i2c_pnx_controller_suspend NULL +#define i2c_pnx_controller_resume NULL +#endif static int __devinit i2c_pnx_probe(struct platform_device *pdev) { unsigned long tmp; int ret = 0; struct i2c_pnx_algo_data *alg_data; - int freq_mhz; + unsigned long freq; struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data; - if (!i2c_pnx || !i2c_pnx->adapter) { + if (!i2c_pnx || !i2c_pnx->name) { dev_err(&pdev->dev, "%s: no platform data supplied\n", __func__); ret = -EINVAL; goto out; } - platform_set_drvdata(pdev, i2c_pnx); - - if (i2c_pnx->calculate_input_freq) - freq_mhz = i2c_pnx->calculate_input_freq(pdev); - else { - freq_mhz = PNX_DEFAULT_FREQ; - dev_info(&pdev->dev, "Setting bus frequency to default value: " - "%d MHz\n", freq_mhz); + alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL); + if (!alg_data) { + ret = -ENOMEM; + goto err_kzalloc; } - i2c_pnx->adapter->algo = &pnx_algorithm; + platform_set_drvdata(pdev, alg_data); + + strlcpy(alg_data->adapter.name, i2c_pnx->name, + sizeof(alg_data->adapter.name)); + alg_data->adapter.dev.parent = &pdev->dev; + alg_data->adapter.algo = &pnx_algorithm; + alg_data->adapter.algo_data = alg_data; + alg_data->adapter.nr = pdev->id; + alg_data->i2c_pnx = i2c_pnx; + + alg_data->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(alg_data->clk)) { + ret = PTR_ERR(alg_data->clk); + goto out_drvdata; + } - alg_data = i2c_pnx->adapter->algo_data; init_timer(&alg_data->mif.timer); alg_data->mif.timer.function = i2c_pnx_timeout; - alg_data->mif.timer.data = (unsigned long)i2c_pnx->adapter; + alg_data->mif.timer.data = (unsigned long)alg_data; /* Register I/O resource */ - if (!request_mem_region(alg_data->base, I2C_PNX_REGION_SIZE, + if (!request_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE, pdev->name)) { dev_err(&pdev->dev, "I/O region 0x%08x for I2C already in use.\n", - alg_data->base); + i2c_pnx->base); ret = -ENODEV; - goto out_drvdata; + goto out_clkget; } - if (!(alg_data->ioaddr = - (u32)ioremap(alg_data->base, I2C_PNX_REGION_SIZE))) { + alg_data->ioaddr = ioremap(i2c_pnx->base, I2C_PNX_REGION_SIZE); + if (!alg_data->ioaddr) { dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n"); ret = -ENOMEM; goto out_release; } - i2c_pnx->set_clock_run(pdev); + ret = clk_enable(alg_data->clk); + if (ret) + goto out_unmap; + + freq = clk_get_rate(alg_data->clk); /* * Clock Divisor High This value is the number of system clocks @@ -620,45 +642,47 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) * the deglitching filter length. */ - tmp = ((freq_mhz * 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2; + tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2; iowrite32(tmp, I2C_REG_CKH(alg_data)); iowrite32(tmp, I2C_REG_CKL(alg_data)); iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data)); if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) { ret = -ENODEV; - goto out_unmap; + goto out_clock; } init_completion(&alg_data->mif.complete); - ret = request_irq(alg_data->irq, i2c_pnx_interrupt, - 0, pdev->name, i2c_pnx->adapter); + ret = request_irq(i2c_pnx->irq, i2c_pnx_interrupt, + 0, pdev->name, alg_data); if (ret) goto out_clock; /* Register this adapter with the I2C subsystem */ - i2c_pnx->adapter->dev.parent = &pdev->dev; - i2c_pnx->adapter->nr = pdev->id; - ret = i2c_add_numbered_adapter(i2c_pnx->adapter); + ret = i2c_add_adapter(&alg_data->adapter); if (ret < 0) { dev_err(&pdev->dev, "I2C: Failed to add bus\n"); goto out_irq; } dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n", - i2c_pnx->adapter->name, alg_data->base, alg_data->irq); + alg_data->adapter.name, i2c_pnx->base, i2c_pnx->irq); return 0; out_irq: - free_irq(alg_data->irq, i2c_pnx->adapter); + free_irq(i2c_pnx->irq, alg_data); out_clock: - i2c_pnx->set_clock_stop(pdev); + clk_disable(alg_data->clk); out_unmap: - iounmap((void *)alg_data->ioaddr); + iounmap(alg_data->ioaddr); out_release: - release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE); + release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE); +out_clkget: + clk_put(alg_data->clk); out_drvdata: + kfree(alg_data); +err_kzalloc: platform_set_drvdata(pdev, NULL); out: return ret; @@ -666,15 +690,16 @@ out: static int __devexit i2c_pnx_remove(struct platform_device *pdev) { - struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); - struct i2c_adapter *adap = i2c_pnx->adapter; - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - - free_irq(alg_data->irq, i2c_pnx->adapter); - i2c_del_adapter(adap); - i2c_pnx->set_clock_stop(pdev); - iounmap((void *)alg_data->ioaddr); - release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE); + struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); + struct i2c_pnx_data *i2c_pnx = alg_data->i2c_pnx; + + free_irq(i2c_pnx->irq, alg_data); + i2c_del_adapter(&alg_data->adapter); + clk_disable(alg_data->clk); + iounmap(alg_data->ioaddr); + release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE); + clk_put(alg_data->clk); + kfree(alg_data); platform_set_drvdata(pdev, NULL); return 0; diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 430a5848a9a5..c7a9479934af 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -96,9 +96,6 @@ static void wdt_enable(void) { spin_lock(&io_lock); - if (wdt_clk) - clk_set_rate(wdt_clk, 1); - /* stop counter, initiate counter reset */ __raw_writel(RESET_COUNT, WDTIM_CTRL(wdt_base)); /*wait for reset to complete. 100% guarantee event */ @@ -125,19 +122,25 @@ static void wdt_disable(void) spin_lock(&io_lock); __raw_writel(0, WDTIM_CTRL(wdt_base)); /*stop counter */ - if (wdt_clk) - clk_set_rate(wdt_clk, 0); spin_unlock(&io_lock); } static int pnx4008_wdt_open(struct inode *inode, struct file *file) { + int ret; + if (test_and_set_bit(WDT_IN_USE, &wdt_status)) return -EBUSY; clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + ret = clk_enable(wdt_clk); + if (ret) { + clear_bit(WDT_IN_USE, &wdt_status); + return ret; + } + wdt_enable(); return nonseekable_open(inode, file); @@ -225,6 +228,7 @@ static int pnx4008_wdt_release(struct inode *inode, struct file *file) printk(KERN_WARNING "WATCHDOG: Device closed unexpectdly\n"); wdt_disable(); + clk_disable(wdt_clk); clear_bit(WDT_IN_USE, &wdt_status); clear_bit(WDT_OK_TO_CLOSE, &wdt_status); @@ -273,25 +277,33 @@ static int __devinit pnx4008_wdt_probe(struct platform_device *pdev) } wdt_base = (void __iomem *)IO_ADDRESS(res->start); - wdt_clk = clk_get(&pdev->dev, "wdt_ck"); + wdt_clk = clk_get(&pdev->dev, NULL); if (IS_ERR(wdt_clk)) { ret = PTR_ERR(wdt_clk); release_resource(wdt_mem); kfree(wdt_mem); goto out; - } else - clk_set_rate(wdt_clk, 1); + } + + ret = clk_enable(wdt_clk); + if (ret) { + release_resource(wdt_mem); + kfree(wdt_mem); + goto out; + } ret = misc_register(&pnx4008_wdt_miscdev); if (ret < 0) { printk(KERN_ERR MODULE_NAME "cannot register misc device\n"); release_resource(wdt_mem); kfree(wdt_mem); - clk_set_rate(wdt_clk, 0); + clk_disable(wdt_clk); + clk_put(wdt_clk); } else { boot_status = (__raw_readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ? WDIOF_CARDRESET : 0; wdt_disable(); /*disable for now */ + clk_disable(wdt_clk); set_bit(WDT_DEVICE_INITED, &wdt_status); } @@ -302,11 +314,10 @@ out: static int __devexit pnx4008_wdt_remove(struct platform_device *pdev) { misc_deregister(&pnx4008_wdt_miscdev); - if (wdt_clk) { - clk_set_rate(wdt_clk, 0); - clk_put(wdt_clk); - wdt_clk = NULL; - } + + clk_disable(wdt_clk); + clk_put(wdt_clk); + if (wdt_mem) { release_resource(wdt_mem); kfree(wdt_mem); |