diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-01 09:15:15 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-01 09:15:15 -0800 |
commit | ac0f6f927db539e03e1f3f61bcd4ed57d5cde7a9 (patch) | |
tree | 816e5ac643b15c2050c64a7075f0f7e13d86ea09 /drivers | |
parent | b1bf9368407ae7e89d8a005bb40beb70a41df539 (diff) | |
parent | 9f33be2c3a80bdc2cc08342dd77fac87652e0548 (diff) |
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (100 commits)
ARM: Eliminate decompressor -Dstatic= PIC hack
ARM: 5958/1: ARM: U300: fix inverted clk round rate
ARM: 5956/1: misplaced parentheses
ARM: 5955/1: ep93xx: move timer defines into core.c and document
ARM: 5954/1: ep93xx: move gpio interrupt support to gpio.c
ARM: 5953/1: ep93xx: fix broken build of clock.c
ARM: 5952/1: ARM: MM: Add ARM_L1_CACHE_SHIFT_6 for handle inside each ARCH Kconfig
ARM: 5949/1: NUC900 add gpio virtual memory map
ARM: 5948/1: Enable timer0 to time4 clock support for nuc910
ARM: 5940/2: ARM: MMCI: remove custom DBG macro and printk
ARM: make_coherent(): fix problems with highpte, part 2
MM: Pass a PTE pointer to update_mmu_cache() rather than the PTE itself
ARM: 5945/1: ep93xx: include correct irq.h in core.c
ARM: 5933/1: amba-pl011: support hardware flow control
ARM: 5930/1: Add PKMAP area description to memory.txt.
ARM: 5929/1: Add checks to detect overlap of memory regions.
ARM: 5928/1: Change type of VMALLOC_END to unsigned long.
ARM: 5927/1: Make delimiters of DMA area globally visibly.
ARM: 5926/1: Add "Virtual kernel memory..." printout.
ARM: 5920/1: OMAP4: Enable L2 Cache
...
Fix up trivial conflict in arch/arm/mach-mx25/clock.c
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/i2c/busses/i2c-pnx.c | 285 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.c | 41 | ||||
-rw-r--r-- | drivers/rtc/rtc-pl031.c | 365 | ||||
-rw-r--r-- | drivers/serial/amba-pl011.c | 19 | ||||
-rw-r--r-- | drivers/spi/amba-pl022.c | 18 | ||||
-rw-r--r-- | drivers/watchdog/pnx4008_wdt.c | 39 |
6 files changed, 565 insertions, 202 deletions
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 5d1c2603a13..2b0bd0b042d 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_numbered_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/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 90d168ad03b..84c103a7ee1 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -2,6 +2,7 @@ * linux/drivers/mmc/host/mmci.c - ARM PrimeCell MMCI PL180/1 driver * * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. + * Copyright (C) 2010 ST-Ericsson AB. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -34,9 +35,6 @@ #define DRIVER_NAME "mmci-pl18x" -#define DBG(host,fmt,args...) \ - pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args) - static unsigned int fmax = 515633; /* @@ -105,8 +103,8 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) void __iomem *base; int blksz_bits; - DBG(host, "blksz %04x blks %04x flags %08x\n", - data->blksz, data->blocks, data->flags); + dev_dbg(mmc_dev(host->mmc), "blksz %04x blks %04x flags %08x\n", + data->blksz, data->blocks, data->flags); host->data = data; host->size = data->blksz; @@ -155,7 +153,7 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) { void __iomem *base = host->base; - DBG(host, "op %02x arg %08x flags %08x\n", + dev_dbg(mmc_dev(host->mmc), "op %02x arg %08x flags %08x\n", cmd->opcode, cmd->arg, cmd->flags); if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) { @@ -184,8 +182,20 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, { if (status & MCI_DATABLOCKEND) { host->data_xfered += data->blksz; +#ifdef CONFIG_ARCH_U300 + /* + * On the U300 some signal or other is + * badly routed so that a data write does + * not properly terminate with a MCI_DATAEND + * status flag. This quirk will make writes + * work again. + */ + if (data->flags & MMC_DATA_WRITE) + status |= MCI_DATAEND; +#endif } if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { + dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status); if (status & MCI_DATACRCFAIL) data->error = -EILSEQ; else if (status & MCI_DATATIMEOUT) @@ -307,7 +317,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) status = readl(base + MMCISTATUS); - DBG(host, "irq1 %08x\n", status); + dev_dbg(mmc_dev(host->mmc), "irq1 (pio) %08x\n", status); do { unsigned long flags; @@ -401,7 +411,7 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) status &= readl(host->base + MMCIMASK0); writel(status, host->base + MMCICLEAR); - DBG(host, "irq0 %08x\n", status); + dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status); data = host->data; if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN| @@ -428,8 +438,8 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) WARN_ON(host->mrq != NULL); if (mrq->data && !is_power_of_2(mrq->data->blksz)) { - printk(KERN_ERR "%s: Unsupported block size (%d bytes)\n", - mmc_hostname(mmc), mrq->data->blksz); + dev_err(mmc_dev(mmc), "unsupported block size (%d bytes)\n", + mrq->data->blksz); mrq->cmd->error = -EINVAL; mmc_request_done(mmc, mrq); return; @@ -582,8 +592,8 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) host->hw_designer = amba_manf(dev); host->hw_revision = amba_rev(dev); - DBG(host, "designer ID = 0x%02x\n", host->hw_designer); - DBG(host, "revision = 0x%01x\n", host->hw_revision); + dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer); + dev_dbg(mmc_dev(mmc), "revision = 0x%01x\n", host->hw_revision); host->clk = clk_get(&dev->dev, NULL); if (IS_ERR(host->clk)) { @@ -608,7 +618,8 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) if (ret < 0) goto clk_disable; host->mclk = clk_get_rate(host->clk); - DBG(host, "eventual mclk rate: %u Hz\n", host->mclk); + dev_dbg(mmc_dev(mmc), "eventual mclk rate: %u Hz\n", + host->mclk); } host->base = ioremap(dev->res.start, resource_size(&dev->res)); if (!host->base) { @@ -619,6 +630,8 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) mmc->ops = &mmci_ops; mmc->f_min = (host->mclk + 511) / 512; mmc->f_max = min(host->mclk, fmax); + dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); + #ifdef CONFIG_REGULATOR /* If we're using the regulator framework, try to fetch a regulator */ host->vcc = regulator_get(&dev->dev, "vmmc"); @@ -712,7 +725,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) mmc_add_host(mmc); - printk(KERN_INFO "%s: MMCI rev %x cfg %02x at 0x%016llx irq %d,%d\n", + dev_info(&dev->dev, "%s: MMCI rev %x cfg %02x at 0x%016llx irq %d,%d\n", mmc_hostname(mmc), amba_rev(dev), amba_config(dev), (unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]); diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 0264b117893..c256aacfa95 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -7,6 +7,9 @@ * * Copyright 2006 (c) MontaVista Software, Inc. * + * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> + * Copyright 2010 (c) ST-Ericsson AB + * * 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; either version @@ -18,6 +21,9 @@ #include <linux/interrupt.h> #include <linux/amba/bus.h> #include <linux/io.h> +#include <linux/bcd.h> +#include <linux/delay.h> +#include <linux/version.h> /* * Register definitions @@ -30,35 +36,207 @@ #define RTC_RIS 0x14 /* Raw interrupt status register */ #define RTC_MIS 0x18 /* Masked interrupt status register */ #define RTC_ICR 0x1c /* Interrupt clear register */ +/* ST variants have additional timer functionality */ +#define RTC_TDR 0x20 /* Timer data read register */ +#define RTC_TLR 0x24 /* Timer data load register */ +#define RTC_TCR 0x28 /* Timer control register */ +#define RTC_YDR 0x30 /* Year data read register */ +#define RTC_YMR 0x34 /* Year match register */ +#define RTC_YLR 0x38 /* Year data load register */ + +#define RTC_CR_CWEN (1 << 26) /* Clockwatch enable bit */ + +#define RTC_TCR_EN (1 << 1) /* Periodic timer enable bit */ + +/* Common bit definitions for Interrupt status and control registers */ +#define RTC_BIT_AI (1 << 0) /* Alarm interrupt bit */ +#define RTC_BIT_PI (1 << 1) /* Periodic interrupt bit. ST variants only. */ + +/* Common bit definations for ST v2 for reading/writing time */ +#define RTC_SEC_SHIFT 0 +#define RTC_SEC_MASK (0x3F << RTC_SEC_SHIFT) /* Second [0-59] */ +#define RTC_MIN_SHIFT 6 +#define RTC_MIN_MASK (0x3F << RTC_MIN_SHIFT) /* Minute [0-59] */ +#define RTC_HOUR_SHIFT 12 +#define RTC_HOUR_MASK (0x1F << RTC_HOUR_SHIFT) /* Hour [0-23] */ +#define RTC_WDAY_SHIFT 17 +#define RTC_WDAY_MASK (0x7 << RTC_WDAY_SHIFT) /* Day of Week [1-7] 1=Sunday */ +#define RTC_MDAY_SHIFT 20 +#define RTC_MDAY_MASK (0x1F << RTC_MDAY_SHIFT) /* Day of Month [1-31] */ +#define RTC_MON_SHIFT 25 +#define RTC_MON_MASK (0xF << RTC_MON_SHIFT) /* Month [1-12] 1=January */ + +#define RTC_TIMER_FREQ 32768 struct pl031_local { struct rtc_device *rtc; void __iomem *base; + u8 hw_designer; + u8 hw_revision:4; }; -static irqreturn_t pl031_interrupt(int irq, void *dev_id) +static int pl031_alarm_irq_enable(struct device *dev, + unsigned int enabled) +{ + struct pl031_local *ldata = dev_get_drvdata(dev); + unsigned long imsc; + + /* Clear any pending alarm interrupts. */ + writel(RTC_BIT_AI, ldata->base + RTC_ICR); + + imsc = readl(ldata->base + RTC_IMSC); + + if (enabled == 1) + writel(imsc | RTC_BIT_AI, ldata->base + RTC_IMSC); + else + writel(imsc & ~RTC_BIT_AI, ldata->base + RTC_IMSC); + + return 0; +} + +/* + * Convert Gregorian date to ST v2 RTC format. + */ +static int pl031_stv2_tm_to_time(struct device *dev, + struct rtc_time *tm, unsigned long *st_time, + unsigned long *bcd_year) +{ + int year = tm->tm_year + 1900; + int wday = tm->tm_wday; + + /* wday masking is not working in hardware so wday must be valid */ + if (wday < -1 || wday > 6) { + dev_err(dev, "invalid wday value %d\n", tm->tm_wday); + return -EINVAL; + } else if (wday == -1) { + /* wday is not provided, calculate it here */ + unsigned long time; + struct rtc_time calc_tm; + + rtc_tm_to_time(tm, &time); + rtc_time_to_tm(time, &calc_tm); + wday = calc_tm.tm_wday; + } + + *bcd_year = (bin2bcd(year % 100) | bin2bcd(year / 100) << 8); + + *st_time = ((tm->tm_mon + 1) << RTC_MON_SHIFT) + | (tm->tm_mday << RTC_MDAY_SHIFT) + | ((wday + 1) << RTC_WDAY_SHIFT) + | (tm->tm_hour << RTC_HOUR_SHIFT) + | (tm->tm_min << RTC_MIN_SHIFT) + | (tm->tm_sec << RTC_SEC_SHIFT); + + return 0; +} + +/* + * Convert ST v2 RTC format to Gregorian date. + */ +static int pl031_stv2_time_to_tm(unsigned long st_time, unsigned long bcd_year, + struct rtc_time *tm) +{ + tm->tm_year = bcd2bin(bcd_year) + (bcd2bin(bcd_year >> 8) * 100); + tm->tm_mon = ((st_time & RTC_MON_MASK) >> RTC_MON_SHIFT) - 1; + tm->tm_mday = ((st_time & RTC_MDAY_MASK) >> RTC_MDAY_SHIFT); + tm->tm_wday = ((st_time & RTC_WDAY_MASK) >> RTC_WDAY_SHIFT) - 1; + tm->tm_hour = ((st_time & RTC_HOUR_MASK) >> RTC_HOUR_SHIFT); + tm->tm_min = ((st_time & RTC_MIN_MASK) >> RTC_MIN_SHIFT); + tm->tm_sec = ((st_time & RTC_SEC_MASK) >> RTC_SEC_SHIFT); + + tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); + tm->tm_year -= 1900; + + return 0; +} + +static int pl031_stv2_read_time(struct device *dev, struct rtc_time *tm) +{ + struct pl031_local *ldata = dev_get_drvdata(dev); + + pl031_stv2_time_to_tm(readl(ldata->base + RTC_DR), + readl(ldata->base + RTC_YDR), tm); + + return 0; +} + +static int pl031_stv2_set_time(struct device *dev, struct rtc_time *tm) +{ + unsigned long time; + unsigned long bcd_year; + struct pl031_local *ldata = dev_get_drvdata(dev); + int ret; + + ret = pl031_stv2_tm_to_time(dev, tm, &time, &bcd_year); + if (ret == 0) { + writel(bcd_year, ldata->base + RTC_YLR); + writel(time, ldata->base + RTC_LR); + } + + return ret; +} + +static int pl031_stv2_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) { - struct rtc_device *rtc = dev_id; + struct pl031_local *ldata = dev_get_drvdata(dev); + int ret; - rtc_update_irq(rtc, 1, RTC_AF); + ret = pl031_stv2_time_to_tm(readl(ldata->base + RTC_MR), + readl(ldata->base + RTC_YMR), &alarm->time); |