[U-Boot] [PATCH] i2c: adding driver for pxa27x, pxa3xx, pxa25x

Cc: Marek Vasut marex@denx.de Cc: Heiko Schocher hs@denx.de Signed-off-by: Andrew Ruder andrew.ruder@elecsyscorp.com ---
This driver was written before the driver model stuff was really around (or at least based on a U-Boot version that only had very preliminary support) so there might be some older conventions in use here. I have tested on a PXA270 board running upstream master with this driver, however - so to some extent this all still works fine. Let me know if things need to change to be accepted, and I'll try to find some time to update!
drivers/i2c/Makefile | 1 + drivers/i2c/pxa_i2c.c | 796 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 797 insertions(+) create mode 100644 drivers/i2c/pxa_i2c.c
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 9b45248..cf2c8a8 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_SYS_I2C_MXS) += mxs_i2c.o obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o obj-$(CONFIG_SYS_I2C_PPC4XX) += ppc4xx_i2c.o +obj-$(CONFIG_SYS_I2C_PXA) += pxa_i2c.o obj-$(CONFIG_SYS_I2C_RCAR) += rcar_i2c.o obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o diff --git a/drivers/i2c/pxa_i2c.c b/drivers/i2c/pxa_i2c.c new file mode 100644 index 0000000..859d6cf --- /dev/null +++ b/drivers/i2c/pxa_i2c.c @@ -0,0 +1,796 @@ +/* + * pxa_i2c.c + * + * I2C adapter for the PXA I2C bus access. + * + * Copyright (C) 2002 Intrinsyc Software Inc. + * Copyright (C) 2004-2005 Deep Blue Solutions Ltd. + * Copyright (C) 2014 Andrew Ruder + * + * 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 + * published by the Free Software Foundation. + * + * This is a heavily modified version of the PXA I2C driver from the Linux + * kernel 3.15.10. + */ + +#include <common.h> +#include <compiler.h> +#include <i2c.h> +#include <asm/arch/pxa-regs.h> + +#include <asm/errno.h> +#include <asm/io.h> + +#define MAX_TRANSFER_MS 5000 +#define WAIT_MASTER_MS 64 +#define ABORT_LENGTH_MS 50 + +/* Set up some defaults for various configurable pieces of this driver + * so that most of the time we don't need extra things defined + */ +#if !defined(CONFIG_SYS_PXA_STD_I2C_SPEED) +#define CONFIG_SYS_PXA_STD_I2C_SPEED 100000 +#endif + +#if !defined(CONFIG_SYS_PXA_STD_I2C_SLAVE) +#define CONFIG_SYS_PXA_STD_I2C_SLAVE 1 +#endif + +#if !defined(CONFIG_SYS_PXA_PWR_I2C_SPEED) +#define CONFIG_SYS_PXA_PWR_I2C_SPEED 40000 +#endif + +#if !defined(CONFIG_SYS_PXA_PWR_I2C_SLAVE) +#define CONFIG_SYS_PXA_PWR_I2C_SLAVE 1 +#endif + +#if defined(CONFIG_CPU_MONAHANS) && defined(CONFIG_PXA_PWR_I2C) +#warning Monahans + PWRI2C is unlikely to work without additional testing +#endif + +/* ICR initialize bit values +* +* 15. FM 0 (100 Khz operation) +* 14. UR 0 (No unit reset) +* 13. SADIE 0 (Disables the unit from interrupting on slave addresses +* matching its slave address) +* 12. ALDIE 0 (Disables the unit from interrupt when it loses arbitration +* in master mode) +* 11. SSDIE 0 (Disables interrupts from a slave stop detected, in slave mode) +* 10. BEIE 1 (Enable interrupts from detected bus errors, no ACK sent) +* 9. IRFIE 1 (Enable interrupts from full buffer received) +* 8. ITEIE 1 (Enables the I2C unit to interrupt when transmit buffer empty) +* 7. GCD 1 (Disables i2c unit response to general call messages as a slave) +* 6. IUE 0 (Disable unit until we change settings) +* 5. SCLE 1 (Enables the i2c clock output for master mode (drives SCL) +* 4. MA 0 (Only send stop with the ICR stop bit) +* 3. TB 0 (We are not transmitting a byte initially) +* 2. ACKNAK 0 (Send an ACK after the unit receives a byte) +* 1. STOP 0 (Do not send a STOP) +* 0. START 0 (Do not send a START) +* +*/ +#define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE) + +/* I2C status register init values + * + * 10. BED 1 (Clear bus error detected) + * 9. SAD 1 (Clear slave address detected) + * 7. IRF 1 (Clear IDBR Receive Full) + * 6. ITE 1 (Clear IDBR Transmit Empty) + * 5. ALD 1 (Clear Arbitration Loss Detected) + * 4. SSD 1 (Clear Slave Stop Detected) + */ +#define I2C_ISR_INIT 0x7FF /* status register init */ + +#define dev_dbg(dev, fmt, args...) \ + debug("pxai2c%d: " fmt, (dev)->hwadapnr, ##args) +#define dev_err(dev, fmt, args...) \ + printf("pxai2c%d: " fmt, (dev)->hwadapnr, ##args) + +enum i2c_code { + I2C_SUCCESS = 0, + I2C_RETRY, + I2C_NAK, + I2C_BUS_ERROR, + I2C_TIMEOUT, + I2C_OTHER_ERROR, + I2C_ALL_RETRIES, + I2C_CONTINUE +}; + +/* + * I2C bit definitions + */ + +#define ICR_START (1 << 0) /* start bit */ +#define ICR_STOP (1 << 1) /* stop bit */ +#define ICR_ACKNAK (1 << 2) /* send ACK(0) or NAK(1) */ +#define ICR_TB (1 << 3) /* transfer byte bit */ +#define ICR_MA (1 << 4) /* master abort */ +#define ICR_SCLE (1 << 5) /* master clock enable */ +#define ICR_IUE (1 << 6) /* unit enable */ +#define ICR_GCD (1 << 7) /* general call disable */ +#define ICR_ITEIE (1 << 8) /* enable tx interrupts */ +#define ICR_IRFIE (1 << 9) /* enable rx interrupts */ +#define ICR_BEIE (1 << 10) /* enable bus error ints */ +#define ICR_SSDIE (1 << 11) /* slave STOP detected int enable */ +#define ICR_ALDIE (1 << 12) /* enable arbitration interrupt */ +#define ICR_SADIE (1 << 13) /* slave address detected int enable */ +#define ICR_UR (1 << 14) /* unit reset */ +#define ICR_FM (1 << 15) /* fast mode */ +#define ICR_HS (1 << 16) /* High Speed mode */ +#define ICR_GPIOEN (1 << 19) /* enable GPIO mode for SCL in HS */ + +#define ISR_RWM (1 << 0) /* read/write mode */ +#define ISR_ACKNAK (1 << 1) /* ack/nak status */ +#define ISR_UB (1 << 2) /* unit busy */ +#define ISR_IBB (1 << 3) /* bus busy */ +#define ISR_SSD (1 << 4) /* slave stop detected */ +#define ISR_ALD (1 << 5) /* arbitration loss detected */ +#define ISR_ITE (1 << 6) /* tx buffer empty */ +#define ISR_IRF (1 << 7) /* rx buffer full */ +#define ISR_GCAD (1 << 8) /* general call address detected */ +#define ISR_SAD (1 << 9) /* slave address detected */ +#define ISR_BED (1 << 10) /* bus error no ACK/NAK */ + +struct pxa_i2c_msg { + u16 addr; + u16 flags; +#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ +#define I2C_M_RD 0x0001 /* read data, from slave to master */ +#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */ +#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ +#define I2C_M_FIRST 0x0800 /* First message in a chain */ + u16 len; + u8 *buf; +}; + +struct pxa_i2c_state { + struct pxa_i2c_msg *msg; + unsigned int msg_num; + unsigned int msg_ptr; +}; + +#define STD_I2C_BASE 0x40301680 +#if defined(CONFIG_CPU_PXA27X) || defined(CONFIG_CPU_PXA25X) +#define PWR_I2C_BASE 0x40f00180 +#define IBMR_OFFSET 0x00 +#define IDBR_OFFSET 0x08 +#define ICR_OFFSET 0x10 +#define ISR_OFFSET 0x18 +#define ISAR_OFFSET 0x20 +#elif defined(CONFIG_CPU_MONAHANS) +#define PWR_I2C_BASE 0x40f500c0 +#define IBMR_OFFSET 0x00 +#define IDBR_OFFSET 0x04 +#define ICR_OFFSET 0x08 +#define ISR_OFFSET 0x0c +#define ISAR_OFFSET 0x10 +#endif + +static inline void __iomem * +pxa_i2c_base(const struct i2c_adapter *adap) +{ + return (adap->hwadapnr == 0) ? (void *)STD_I2C_BASE : (void *)PWR_I2C_BASE; +} + +static inline void __iomem * +pxa_i2c_ibmr(const struct i2c_adapter *adap) +{ + return (void *)((char *)pxa_i2c_base(adap) + IBMR_OFFSET); +} + +static inline void __iomem * +pxa_i2c_idbr(const struct i2c_adapter *adap) +{ + return (void *)((char *)pxa_i2c_base(adap) + IDBR_OFFSET); +} + +static inline void __iomem * +pxa_i2c_icr(const struct i2c_adapter *adap) +{ + return (void *)((char *)pxa_i2c_base(adap) + ICR_OFFSET); +} + +static inline void __iomem * +pxa_i2c_isr(const struct i2c_adapter *adap) +{ + return (void *)((char *)pxa_i2c_base(adap) + ISR_OFFSET); +} + +static inline void __iomem * +pxa_i2c_isar(const struct i2c_adapter *adap) +{ + return (void *)((char *)pxa_i2c_base(adap) + ISAR_OFFSET); +} + +#define _IBMR(adap) pxa_i2c_ibmr(adap) +#define _IDBR(adap) pxa_i2c_idbr(adap) +#define _ICR(adap) pxa_i2c_icr(adap) +#define _ISR(adap) pxa_i2c_isr(adap) +#define _ISAR(adap) pxa_i2c_isar(adap) + +#ifdef DEBUG + +struct bits { + u32 mask; + const char *set; + const char *unset; +}; +#define PXA_BIT(m, s, u) { .mask = m, .set = s, .unset = u } + +static const struct bits isr_bits[] = { + PXA_BIT(ISR_RWM, "RX", "TX"), + PXA_BIT(ISR_ACKNAK, "NAK", "ACK"), + PXA_BIT(ISR_UB, "Bsy", "Rdy"), + PXA_BIT(ISR_IBB, "BusBsy", "BusRdy"), + PXA_BIT(ISR_SSD, "SlaveStop", NULL), + PXA_BIT(ISR_ALD, "ALD", NULL), + PXA_BIT(ISR_ITE, "TxEmpty", NULL), + PXA_BIT(ISR_IRF, "RxFull", NULL), + PXA_BIT(ISR_GCAD, "GenCall", NULL), + PXA_BIT(ISR_SAD, "SlaveAddr", NULL), + PXA_BIT(ISR_BED, "BusErr", NULL), +}; + +static const struct bits icr_bits[] = { + PXA_BIT(ICR_START, "START", NULL), + PXA_BIT(ICR_STOP, "STOP", NULL), + PXA_BIT(ICR_ACKNAK, "ACKNAK", NULL), + PXA_BIT(ICR_TB, "TB", NULL), + PXA_BIT(ICR_MA, "MA", NULL), + PXA_BIT(ICR_SCLE, "SCLE", "scle"), + PXA_BIT(ICR_IUE, "IUE", "iue"), + PXA_BIT(ICR_GCD, "GCD", NULL), + PXA_BIT(ICR_ITEIE, "ITEIE", NULL), + PXA_BIT(ICR_IRFIE, "IRFIE", NULL), + PXA_BIT(ICR_BEIE, "BEIE", NULL), + PXA_BIT(ICR_SSDIE, "SSDIE", NULL), + PXA_BIT(ICR_ALDIE, "ALDIE", NULL), + PXA_BIT(ICR_SADIE, "SADIE", NULL), + PXA_BIT(ICR_UR, "UR", "ur"), +}; + +static inline void +decode_bits(const char *prefix, const struct bits *bits, int num, u32 val) +{ + printf("%s %08x: ", prefix, val); + while (num--) { + const char *str = val & bits->mask ? bits->set : bits->unset; + if (str) + printf("%s ", str); + bits++; + } + printf("\n"); +} + +static void +decode_ISR(unsigned int val) +{ + decode_bits("ISR", isr_bits, ARRAY_SIZE(isr_bits), val); +} + +static void +decode_ICR(unsigned int val) +{ + decode_bits("ICR", icr_bits, ARRAY_SIZE(icr_bits), val); +} + +static void i2c_pxa_show_state(struct i2c_adapter *adap, int lno, + const char *fname) +{ + u32 icr = readl(_ICR(adap)); + u32 isr = readl(_ISR(adap)); + dev_dbg(adap, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno, + icr, isr, readl(_IBMR(adap))); + printf(" "); + decode_ICR(icr); + printf(" "); + decode_ISR(isr); +} + +#define show_state(adap) i2c_pxa_show_state(adap, __LINE__, __func__) + +static void i2c_pxa_scream_blue_murder(struct i2c_adapter *adap, + struct pxa_i2c_state *msgs, + const char *why) +{ + dev_dbg(adap, "error: %s\n", why); + show_state(adap); +} + +#else /* ifdef DEBUG */ + +#define show_state(adap) do { } while (0) +#define decode_ISR(val) do { } while (0) +#define decode_ICR(val) do { } while (0) +#define i2c_pxa_scream_blue_murder(adap, msgs, why) do { } while (0) + +#endif /* ifdef DEBUG / else */ + +static enum i2c_code +i2c_pxa_handler(struct i2c_adapter *adap, + struct pxa_i2c_state *msgs); + +static void +i2c_pxa_abort(struct i2c_adapter *adap) +{ + unsigned long long end; + + end = get_ticks() + (get_tbclk() / 1000) * ABORT_LENGTH_MS; + + while ((get_ticks() < end) && + (readl(_IBMR(adap)) & 0x1) == 0) { + unsigned long icr = readl(_ICR(adap)); + + icr &= ~ICR_START; + icr |= ICR_ACKNAK | ICR_STOP | ICR_TB; + + writel(icr, _ICR(adap)); + + show_state(adap); + + mdelay(1); + } + + writel(readl(_ICR(adap)) & ~(ICR_MA | ICR_START | ICR_STOP), + _ICR(adap)); +} + +static void +i2c_pxa_reset(struct i2c_adapter *adap) +{ + /* abort any transfer currently under way */ + i2c_pxa_abort(adap); + + /* reset according to 9.8 */ + writel(ICR_UR, _ICR(adap)); + writel(I2C_ISR_INIT, _ISR(adap)); + writel(readl(_ICR(adap)) & ~ICR_UR, _ICR(adap)); + + writel(adap->slaveaddr, _ISAR(adap)); + + /* set control register values */ + writel(I2C_ICR_INIT, _ICR(adap)); + + /* enable unit */ + writel(readl(_ICR(adap)) | ICR_IUE, _ICR(adap)); + udelay(100); +} + +static inline unsigned int +i2c_pxa_addr_byte(struct pxa_i2c_msg *msg) +{ + unsigned int addr = (msg->addr & 0x7f) << 1; + + if (msg->flags & I2C_M_RD) + addr |= 1; + + return addr; +} + +static inline void +i2c_pxa_start_message(struct i2c_adapter *adap, struct pxa_i2c_state *msgs) +{ + u32 icr; + /* + * Step 1: target slave address into IDBR + */ + writel(i2c_pxa_addr_byte(msgs->msg), _IDBR(adap)); + + /* + * Step 2: initiate the write. + */ + icr = readl(_ICR(adap)) & ~(ICR_STOP | ICR_ALDIE); + writel(icr | ICR_START | ICR_TB, _ICR(adap)); +} + +static inline void +i2c_pxa_stop_message(struct i2c_adapter *adap, struct pxa_i2c_state *msgs) +{ + u32 icr; + + /* + * Clear the STOP and ACK flags + */ + icr = readl(_ICR(adap)); + icr &= ~(ICR_STOP | ICR_ACKNAK); + writel(icr, _ICR(adap)); +} + +static enum i2c_code +i2c_pxa_pio_set_master(struct i2c_adapter *adap) +{ + /* make timeout the same as for interrupt based functions */ + unsigned long long end; + + /* + * Wait for the bus to become free. + */ + end = get_ticks() + (get_tbclk() / 1000) * WAIT_MASTER_MS; + while (readl(_ISR(adap)) & (ISR_IBB | ISR_UB)) { + udelay(1000); + show_state(adap); + if (get_ticks() > end) { + show_state(adap); + dev_err(adap, "i2c_pxa: timeout waiting for bus free\n"); + return I2C_RETRY; + } + } + + /* + * Set master mode. + */ + writel(readl(_ICR(adap)) | ICR_SCLE, _ICR(adap)); + + return I2C_SUCCESS; +} + +static enum i2c_code +i2c_pxa_do_pio_xfer(struct i2c_adapter *adap, + struct pxa_i2c_msg *msg, int num) +{ + unsigned long long end; + enum i2c_code ret; + struct pxa_i2c_state msgs; + + ret = i2c_pxa_pio_set_master(adap); + if (ret) + goto out; + + memset(&msgs, 0, sizeof(msgs)); + msgs.msg = msg; + msgs.msg_num = num; + msg->flags |= I2C_M_FIRST; + + i2c_pxa_start_message(adap, &msgs); + + ret = I2C_TIMEOUT; + end = get_ticks() + (get_tbclk() / 1000) * MAX_TRANSFER_MS; + while (get_ticks() < end) { + enum i2c_code temp_ret; + temp_ret = i2c_pxa_handler(adap, &msgs); + if (temp_ret != I2C_CONTINUE) { + ret = temp_ret; + break; + } + udelay(10); + } + + i2c_pxa_stop_message(adap, &msgs); + +out: + if (ret == I2C_TIMEOUT) + i2c_pxa_scream_blue_murder(adap, &msgs, "timeout"); + + return ret; +} + +static int +i2c_pxa_pio_xfer(struct i2c_adapter *adap, + struct pxa_i2c_msg msgs[], int num) +{ + int ret, i; + + /* If the I2C controller is disabled we need to reset it + (probably due to a suspend/resume destroying state). We do + this here as we can then avoid worrying about resuming the + controller before its users. */ + if (!(readl(_ICR(adap)) & ICR_IUE)) + i2c_pxa_reset(adap); + + for (i = 0; i < 5; i++) { + ret = i2c_pxa_do_pio_xfer(adap, msgs, num); + if (ret != I2C_RETRY) { + goto out; + } + + udelay(100); + } + i2c_pxa_scream_blue_murder(adap, NULL, "exhausted retries"); + ret = -EREMOTEIO; + out: + return ret; +} + + +static enum i2c_code +i2c_pxa_irq_txempty(struct i2c_adapter *adap, + struct pxa_i2c_state *msgs, u32 isr) +{ + enum i2c_code ret = I2C_CONTINUE; + u32 icr = readl(_ICR(adap)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB); + + again: + /* + * If ISR_ALD is set, we lost arbitration. + */ + if (isr & ISR_ALD) { + /* + * Do we need to do anything here? The PXA docs + * are vague about what happens. + */ + i2c_pxa_scream_blue_murder(adap, msgs, "ALD set"); + + /* + * We ignore this error. We seem to see spurious ALDs + * for seemingly no reason. If we handle them as I think + * they should, we end up causing an I2C error, which + * is painful for some systems. + */ + return I2C_CONTINUE; + } + + if (isr & ISR_BED) { + ret = I2C_BUS_ERROR; + + /* + * I2C bus error - either the device NAK'd us, or + * something more serious happened. If we were NAK'd + * on the initial address phase, we can retry. + */ + if (isr & ISR_ACKNAK) { + if (msgs->msg_ptr == 0 && (msgs->msg->flags & I2C_M_FIRST) != 0) + ret = I2C_RETRY; + else + ret = I2C_NAK; + } + } else if (isr & ISR_RWM) { + /* + * Read mode. We have just sent the address byte, and + * now we must initiate the transfer. + */ + if (msgs->msg_ptr == msgs->msg->len - 1 && + msgs->msg_num == 1) + icr |= ICR_STOP | ICR_ACKNAK; + + icr |= ICR_ALDIE | ICR_TB; + } else if (msgs->msg_ptr < msgs->msg->len) { + /* + * Write mode. Write the next data byte. + */ + writel(msgs->msg->buf[msgs->msg_ptr++], _IDBR(adap)); + + icr |= ICR_ALDIE | ICR_TB; + + /* + * If this is the last byte of the last message, send + * a STOP. + */ + if (msgs->msg_ptr == msgs->msg->len && + msgs->msg_num == 1) + icr |= ICR_STOP; + } else if (msgs->msg_num > 1) { + /* + * Next segment of the message. + */ + msgs->msg_ptr = 0; + msgs->msg_num--; + msgs->msg++; + + /* + * If we aren't doing a repeated start and address, + * go back and try to send the next byte. Note that + * we do not support switching the R/W direction here. + */ + if (msgs->msg->flags & I2C_M_NOSTART) + goto again; + + /* + * Write the next address. + */ + writel(i2c_pxa_addr_byte(msgs->msg), _IDBR(adap)); + + /* + * And trigger a repeated start, and send the byte. + */ + icr &= ~ICR_ALDIE; + icr |= ICR_START | ICR_TB; + } else { + if ((msgs->msg->flags & I2C_M_FIRST) != 0 && + msgs->msg->len == 0) { + /* + * Device probes have a message length of zero + * and need the bus to be reset before it can + * be used again. + */ + i2c_pxa_reset(adap); + } + ret = I2C_SUCCESS; + } + + writel(icr, _ICR(adap)); + show_state(adap); + return ret; +} + +static enum i2c_code +i2c_pxa_irq_rxfull(struct i2c_adapter *adap, + struct pxa_i2c_state *msgs, u32 isr) +{ + u32 icr = readl(_ICR(adap)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB); + enum i2c_code ret = I2C_CONTINUE; + + /* + * Read the byte. + */ + msgs->msg->buf[msgs->msg_ptr++] = readl(_IDBR(adap)); + + if (msgs->msg_ptr < msgs->msg->len) { + /* + * If this is the last byte of the last + * message, send a STOP. + */ + if (msgs->msg_ptr == msgs->msg->len - 1) + icr |= ICR_STOP | ICR_ACKNAK; + + icr |= ICR_ALDIE | ICR_TB; + } else { + ret = I2C_SUCCESS; + } + + writel(icr, _ICR(adap)); + return ret; +} + +#define VALID_INT_SOURCE (ISR_SSD | ISR_ALD | ISR_ITE | ISR_IRF | \ + ISR_SAD | ISR_BED) +static enum i2c_code +i2c_pxa_handler(struct i2c_adapter *adap, + struct pxa_i2c_state *msgs) +{ + u32 isr = readl(_ISR(adap)); + enum i2c_code ret = I2C_CONTINUE; + + dev_dbg(adap, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n", + __func__, isr, readl(_ICR(adap)), readl(_IBMR(adap))); + decode_ISR(isr); + + if (!(isr & VALID_INT_SOURCE)) + return ret; + + show_state(adap); + + /* + * Always clear all pending IRQs. + */ + writel(isr & VALID_INT_SOURCE, _ISR(adap)); + + if (msgs->msg) { + if (ret == I2C_CONTINUE && (isr & ISR_ITE)) + ret = i2c_pxa_irq_txempty(adap, msgs, isr); + if (ret == I2C_CONTINUE && (isr & ISR_IRF)) + ret = i2c_pxa_irq_rxfull(adap, msgs, isr); + } else { + i2c_pxa_scream_blue_murder(adap, msgs, "spurious irq"); + } + return ret; +} + +static void +pxa_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr) +{ + i2c_pxa_reset(adap); +} + +static void __maybe_unused +pxa_i2c_std_init(struct i2c_adapter *adap, int speed, int slaveaddr) +{ +#if defined(CONFIG_CPU_MONAHANS) + writel(readl(CKENB) | CKENB_4_I2C, CKENB); +#else + writel(readl(CKEN) | CKEN14_I2C, CKEN); +#endif + pxa_i2c_init(adap, speed, slaveaddr); +} + +static void __maybe_unused +pxa_i2c_pwr_init(struct i2c_adapter *adap, int speed, int slaveaddr) +{ +#if !defined(CONFIG_CPU_MONAHANS) + writel(readl(PCFR) | PCFR_PI2C_EN, PCFR); + writel(readl(CKEN) | CKEN15_PWRI2C, CKEN); +#endif + pxa_i2c_init(adap, speed, slaveaddr); +} + +static uint8_t * +addr_to_buffer(uint8_t *buffer, uint addr, int alen) +{ + int shift = (alen - 1) * 8; + int i = 0; + while (alen-- > 0) { + buffer[i++] = addr >> shift; + shift -= 8; + } + return buffer; +} + +static int +pxa_i2c_read(struct i2c_adapter *adap, uint8_t chip, uint addr, int alen, + uint8_t *buffer, int len) +{ + uint8_t address_buf[4]; + struct pxa_i2c_msg msgs[2] = { + [0] = { + .addr = chip, + .flags = 0, + .len = alen, + .buf = addr_to_buffer(address_buf, addr, alen), + }, + [1] = { + .addr = chip, + .flags = I2C_M_RD, + .len = len, + .buf = buffer + }, + }; + dev_dbg(adap, "reading %d bytes from 0x%02x[0x%x]\n", + (int)len, (int)chip, (int)addr); + + return i2c_pxa_pio_xfer(adap, msgs, 2); +} + + +static int +pxa_i2c_write(struct i2c_adapter *adap, uint8_t chip, uint addr, + int alen, uint8_t *buffer, int len) +{ + uint8_t address_buf[4]; + struct pxa_i2c_msg msgs[2] = { + [0] = { + .addr = chip, + .flags = 0, + .len = alen, + .buf = addr_to_buffer(address_buf, addr, alen), + }, + [1] = { + .addr = 0, + .flags = I2C_M_NOSTART, + .len = len, + .buf = (uint8_t *)buffer + }, + }; + dev_dbg(adap, "writing %d bytes to 0x%02x[0x%x]\n", + (int)len, (int)chip, (int)addr); + + return i2c_pxa_pio_xfer(adap, msgs, (len == 0 ? 1 : 2)); +} + +static int +pxa_i2c_probe(struct i2c_adapter *adap, uint8_t chip) +{ + struct pxa_i2c_msg msgs[1] = { + [0] = { + .addr = chip, + .flags = 0, + .len = 0, + .buf = 0, + }, + }; + if (adap->slaveaddr == chip) { + return 1; + } + dev_dbg(adap, "probing 0x%02x\n", (int)chip); + + return i2c_pxa_pio_xfer(adap, msgs, 1); +} + +#if defined(CONFIG_PXA_STD_I2C) +U_BOOT_I2C_ADAP_COMPLETE(pxa_std_i2c, pxa_i2c_std_init, pxa_i2c_probe, pxa_i2c_read, + pxa_i2c_write, NULL, CONFIG_SYS_PXA_STD_I2C_SPEED, + CONFIG_SYS_PXA_STD_I2C_SLAVE, 0); +#endif + +#if defined(CONFIG_PXA_PWR_I2C) +U_BOOT_I2C_ADAP_COMPLETE(pxa_pwr_i2c, pxa_i2c_pwr_init, pxa_i2c_probe, pxa_i2c_read, + pxa_i2c_write, NULL, CONFIG_SYS_PXA_PWR_I2C_SPEED, + CONFIG_SYS_PXA_PWR_I2C_SLAVE, 1); +#endif

On Wednesday, August 12, 2015 at 08:43:52 PM, Andrew Ruder wrote:
Commit message is missing :'-(
Cc: Marek Vasut marex@denx.de Cc: Heiko Schocher hs@denx.de Signed-off-by: Andrew Ruder andrew.ruder@elecsyscorp.com
This driver was written before the driver model stuff was really around (or at least based on a U-Boot version that only had very preliminary support) so there might be some older conventions in use here. I have tested on a PXA270 board running upstream master with this driver, however - so to some extent this all still works fine. Let me know if things need to change to be accepted, and I'll try to find some time to update!
drivers/i2c/Makefile | 1 + drivers/i2c/pxa_i2c.c | 796 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 797 insertions(+) create mode 100644 drivers/i2c/pxa_i2c.c
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 9b45248..cf2c8a8 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_SYS_I2C_MXS) += mxs_i2c.o obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o obj-$(CONFIG_SYS_I2C_PPC4XX) += ppc4xx_i2c.o +obj-$(CONFIG_SYS_I2C_PXA) += pxa_i2c.o obj-$(CONFIG_SYS_I2C_RCAR) += rcar_i2c.o obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o diff --git a/drivers/i2c/pxa_i2c.c b/drivers/i2c/pxa_i2c.c new file mode 100644 index 0000000..859d6cf --- /dev/null +++ b/drivers/i2c/pxa_i2c.c @@ -0,0 +1,796 @@ +/*
- pxa_i2c.c
- I2C adapter for the PXA I2C bus access.
- Copyright (C) 2002 Intrinsyc Software Inc.
- Copyright (C) 2004-2005 Deep Blue Solutions Ltd.
- Copyright (C) 2014 Andrew Ruder
- 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
- published by the Free Software Foundation.
- This is a heavily modified version of the PXA I2C driver from the
Linux + * kernel 3.15.10.
- */
+#include <common.h> +#include <compiler.h> +#include <i2c.h> +#include <asm/arch/pxa-regs.h>
+#include <asm/errno.h> +#include <asm/io.h>
+#define MAX_TRANSFER_MS 5000 +#define WAIT_MASTER_MS 64 +#define ABORT_LENGTH_MS 50
+/* Set up some defaults for various configurable pieces of this driver
- so that most of the time we don't need extra things defined
Multiline comment should be of the form:
/* * foo * bar */
- */
+#if !defined(CONFIG_SYS_PXA_STD_I2C_SPEED) +#define CONFIG_SYS_PXA_STD_I2C_SPEED 100000 +#endif
+#if !defined(CONFIG_SYS_PXA_STD_I2C_SLAVE) +#define CONFIG_SYS_PXA_STD_I2C_SLAVE 1 +#endif
+#if !defined(CONFIG_SYS_PXA_PWR_I2C_SPEED) +#define CONFIG_SYS_PXA_PWR_I2C_SPEED 40000 +#endif
+#if !defined(CONFIG_SYS_PXA_PWR_I2C_SLAVE) +#define CONFIG_SYS_PXA_PWR_I2C_SLAVE 1 +#endif
Please remove all this stuff, it's only going to hide bugs.
+#if defined(CONFIG_CPU_MONAHANS) && defined(CONFIG_PXA_PWR_I2C) +#warning Monahans + PWRI2C is unlikely to work without additional testing +#endif
[...]
+#define ISR_ITE (1 << 6) /* tx buffer empty */ +#define ISR_IRF (1 << 7) /* rx buffer full */ +#define ISR_GCAD (1 << 8) /* general call address detected */ +#define ISR_SAD (1 << 9) /* slave address detected */ +#define ISR_BED (1 << 10) /* bus error no ACK/NAK */
+struct pxa_i2c_msg {
- u16 addr;
- u16 flags;
+#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
Be consistent about using 1 << n or 0x0n00 please. Just use the BIT(n) macro.
+#define I2C_M_RD 0x0001 /* read data, from slave to master */ +#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */ +#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING
*/
+#define I2C_M_RECV_LEN 0x0400 /* length will be first received
byte */
+#define I2C_M_FIRST 0x0800 /* First message in a chain */
- u16 len;
- u8 *buf;
+};
+struct pxa_i2c_state {
- struct pxa_i2c_msg *msg;
- unsigned int msg_num;
- unsigned int msg_ptr;
+};
+#define STD_I2C_BASE 0x40301680 +#if defined(CONFIG_CPU_PXA27X) || defined(CONFIG_CPU_PXA25X) +#define PWR_I2C_BASE 0x40f00180 +#define IBMR_OFFSET 0x00 +#define IDBR_OFFSET 0x08 +#define ICR_OFFSET 0x10 +#define ISR_OFFSET 0x18 +#define ISAR_OFFSET 0x20 +#elif defined(CONFIG_CPU_MONAHANS) +#define PWR_I2C_BASE 0x40f500c0 +#define IBMR_OFFSET 0x00 +#define IDBR_OFFSET 0x04 +#define ICR_OFFSET 0x08 +#define ISR_OFFSET 0x0c +#define ISAR_OFFSET 0x10 +#endif
+static inline void __iomem * +pxa_i2c_base(const struct i2c_adapter *adap) +{
- return (adap->hwadapnr == 0) ? (void *)STD_I2C_BASE : (void
*)PWR_I2C_BASE; +}
+static inline void __iomem * +pxa_i2c_ibmr(const struct i2c_adapter *adap) +{
- return (void *)((char *)pxa_i2c_base(adap) + IBMR_OFFSET);
No need for these hideous casts, just use pxa_i2c_base() + OFFSET in the code.
+}
[...]
+static void +i2c_pxa_abort(struct i2c_adapter *adap) +{
- unsigned long long end;
- end = get_ticks() + (get_tbclk() / 1000) * ABORT_LENGTH_MS;
- while ((get_ticks() < end) &&
Please use get_timer() to implement the delay loop.
time = get_timer(0); while (true) { reg = readl(); if (reg & bit) break;
if (get_timer(time) > timeout) return -ETIMEDOUT; }
Also, the lpc32xx patches recently implemented a wait_for_bit() function. If you make this generic, that'd be really cool.
(readl(_IBMR(adap)) & 0x1) == 0) {
unsigned long icr = readl(_ICR(adap));
icr &= ~ICR_START;
icr |= ICR_ACKNAK | ICR_STOP | ICR_TB;
writel(icr, _ICR(adap));
show_state(adap);
mdelay(1);
- }
- writel(readl(_ICR(adap)) & ~(ICR_MA | ICR_START | ICR_STOP),
_ICR(adap));
Please use clrsetbits_le32();
+}
[...]

On Aug 12, 2015, at 2:34 PM, Marek Vasut marex@denx.de wrote:
On Wednesday, August 12, 2015 at 08:43:52 PM, Andrew Ruder wrote:
Commit message is missing :'-(
I actually was going with subject being sufficient on this one. I'll fill in some more info on this as far as origin and what it has been tested on and send in again.
Cc: Marek Vasut marex@denx.de Cc: Heiko Schocher hs@denx.de Signed-off-by: Andrew Ruder andrew.ruder@elecsyscorp.com
This driver was written before the driver model stuff was really around (or at least based on a U-Boot version that only had very preliminary support) so there might be some older conventions in use here. I have tested on a PXA270 board running upstream master with this driver, however - so to some extent this all still works fine. Let me know if things need to change to be accepted, and I'll try to find some time to update!
drivers/i2c/Makefile | 1 + drivers/i2c/pxa_i2c.c | 796 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 797 insertions(+) create mode 100644 drivers/i2c/pxa_i2c.c
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 9b45248..cf2c8a8 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_SYS_I2C_MXS) += mxs_i2c.o obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o obj-$(CONFIG_SYS_I2C_PPC4XX) += ppc4xx_i2c.o +obj-$(CONFIG_SYS_I2C_PXA) += pxa_i2c.o obj-$(CONFIG_SYS_I2C_RCAR) += rcar_i2c.o obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o diff --git a/drivers/i2c/pxa_i2c.c b/drivers/i2c/pxa_i2c.c new file mode 100644 index 0000000..859d6cf --- /dev/null +++ b/drivers/i2c/pxa_i2c.c @@ -0,0 +1,796 @@ +/*
- pxa_i2c.c
- I2C adapter for the PXA I2C bus access.
- Copyright (C) 2002 Intrinsyc Software Inc.
- Copyright (C) 2004-2005 Deep Blue Solutions Ltd.
- Copyright (C) 2014 Andrew Ruder
- 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
- published by the Free Software Foundation.
- This is a heavily modified version of the PXA I2C driver from the
Linux + * kernel 3.15.10.
- */
+#include <common.h> +#include <compiler.h> +#include <i2c.h> +#include <asm/arch/pxa-regs.h>
+#include <asm/errno.h> +#include <asm/io.h>
+#define MAX_TRANSFER_MS 5000 +#define WAIT_MASTER_MS 64 +#define ABORT_LENGTH_MS 50
+/* Set up some defaults for various configurable pieces of this driver
- so that most of the time we don't need extra things defined
Multiline comment should be of the form:
/*
- foo
- bar
*/
- */
+#if !defined(CONFIG_SYS_PXA_STD_I2C_SPEED) +#define CONFIG_SYS_PXA_STD_I2C_SPEED 100000 +#endif
+#if !defined(CONFIG_SYS_PXA_STD_I2C_SLAVE) +#define CONFIG_SYS_PXA_STD_I2C_SLAVE 1 +#endif
+#if !defined(CONFIG_SYS_PXA_PWR_I2C_SPEED) +#define CONFIG_SYS_PXA_PWR_I2C_SPEED 40000 +#endif
+#if !defined(CONFIG_SYS_PXA_PWR_I2C_SLAVE) +#define CONFIG_SYS_PXA_PWR_I2C_SLAVE 1 +#endif
Please remove all this stuff, it's only going to hide bugs.
+#if defined(CONFIG_CPU_MONAHANS) && defined(CONFIG_PXA_PWR_I2C) +#warning Monahans + PWRI2C is unlikely to work without additional testing +#endif
[...]
+#define ISR_ITE (1 << 6) /* tx buffer empty */ +#define ISR_IRF (1 << 7) /* rx buffer full */ +#define ISR_GCAD (1 << 8) /* general call address detected */ +#define ISR_SAD (1 << 9) /* slave address detected */ +#define ISR_BED (1 << 10) /* bus error no ACK/NAK */
+struct pxa_i2c_msg {
- u16 addr;
- u16 flags;
+#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
Be consistent about using 1 << n or 0x0n00 please. Just use the BIT(n) macro.
+#define I2C_M_RD 0x0001 /* read data, from slave to master */ +#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */ +#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING
*/
+#define I2C_M_RECV_LEN 0x0400 /* length will be first received
byte */
+#define I2C_M_FIRST 0x0800 /* First message in a chain */
- u16 len;
- u8 *buf;
+};
+struct pxa_i2c_state {
- struct pxa_i2c_msg *msg;
- unsigned int msg_num;
- unsigned int msg_ptr;
+};
+#define STD_I2C_BASE 0x40301680 +#if defined(CONFIG_CPU_PXA27X) || defined(CONFIG_CPU_PXA25X) +#define PWR_I2C_BASE 0x40f00180 +#define IBMR_OFFSET 0x00 +#define IDBR_OFFSET 0x08 +#define ICR_OFFSET 0x10 +#define ISR_OFFSET 0x18 +#define ISAR_OFFSET 0x20 +#elif defined(CONFIG_CPU_MONAHANS) +#define PWR_I2C_BASE 0x40f500c0 +#define IBMR_OFFSET 0x00 +#define IDBR_OFFSET 0x04 +#define ICR_OFFSET 0x08 +#define ISR_OFFSET 0x0c +#define ISAR_OFFSET 0x10 +#endif
+static inline void __iomem * +pxa_i2c_base(const struct i2c_adapter *adap) +{
- return (adap->hwadapnr == 0) ? (void *)STD_I2C_BASE : (void
*)PWR_I2C_BASE; +}
+static inline void __iomem * +pxa_i2c_ibmr(const struct i2c_adapter *adap) +{
- return (void *)((char *)pxa_i2c_base(adap) + IBMR_OFFSET);
No need for these hideous casts, just use pxa_i2c_base() + OFFSET in the code.
+}
[...]
+static void +i2c_pxa_abort(struct i2c_adapter *adap) +{
- unsigned long long end;
- end = get_ticks() + (get_tbclk() / 1000) * ABORT_LENGTH_MS;
- while ((get_ticks() < end) &&
Please use get_timer() to implement the delay loop.
time = get_timer(0); while (true) { reg = readl(); if (reg & bit) break;
if (get_timer(time) > timeout) return -ETIMEDOUT; }
Also, the lpc32xx patches recently implemented a wait_for_bit() function. If you make this generic, that'd be really cool.
(readl(_IBMR(adap)) & 0x1) == 0) {
unsigned long icr = readl(_ICR(adap));
icr &= ~ICR_START;
icr |= ICR_ACKNAK | ICR_STOP | ICR_TB;
writel(icr, _ICR(adap));
show_state(adap);
mdelay(1);
- }
- writel(readl(_ICR(adap)) & ~(ICR_MA | ICR_START | ICR_STOP),
_ICR(adap));
Please use clrsetbits_le32();
+}
[...]

On Wednesday, August 12, 2015 at 10:19:43 PM, Andrew Ruder wrote:
On Aug 12, 2015, at 2:34 PM, Marek Vasut marex@denx.de wrote:
On Wednesday, August 12, 2015 at 08:43:52 PM, Andrew Ruder wrote:
Commit message is missing :'-(
I actually was going with subject being sufficient on this one. I'll fill in some more info on this as far as origin and what it has been tested on and send in again.
It's really a minor thing, but a commit message should always be present.
Thanks!
Best regards, Marek Vasut

On Wed, Aug 12, 2015 at 09:34:14PM +0200, Marek Vasut wrote:
On Wednesday, August 12, 2015 at 08:43:52 PM, Andrew Ruder wrote:
+#if !defined(CONFIG_SYS_PXA_STD_I2C_SPEED) +#define CONFIG_SYS_PXA_STD_I2C_SPEED 100000 +#endif
+#if !defined(CONFIG_SYS_PXA_STD_I2C_SLAVE) +#define CONFIG_SYS_PXA_STD_I2C_SLAVE 1 +#endif
+#if !defined(CONFIG_SYS_PXA_PWR_I2C_SPEED) +#define CONFIG_SYS_PXA_PWR_I2C_SPEED 40000 +#endif
+#if !defined(CONFIG_SYS_PXA_PWR_I2C_SLAVE) +#define CONFIG_SYS_PXA_PWR_I2C_SLAVE 1 +#endif
Please remove all this stuff, it's only going to hide bugs.
Hide in what way? Just require that ports define them when enabling the i2c driver? ... or don't make it externally configurable?
Thanks, Andrew

On Wed, 2015-08-12 at 13:43 -0500, Andrew Ruder wrote:
Cc: Marek Vasut marex@denx.de Cc: Heiko Schocher hs@denx.de Signed-off-by: Andrew Ruder andrew.ruder@elecsyscorp.com
This driver was written before the driver model stuff was really around (or at least based on a U-Boot version that only had very preliminary support) so there might be some older conventions in use here. I have tested on a PXA270 board running upstream master with this driver, however - so to some extent this all still works fine. Let me know if things need to change to be accepted, and I'll try to find some time to update!
Apart from the missing commit message.
Signed-off-by: Marcel Ziswiler marcel@ziswiler.com
Tested-by: Marcel Ziswiler marcel@ziswiler.com Tested-on: Colibri PXA270 V1.2C, V1.2D, V2.2B, V2.4A on Colibri Evaluation Board V3.1A Note: While power I2C works on the older V1.2C version it does not seem to work on any of the newer ones but this might just be a pin muxing resp. missing pull up issue.

On Sunday, August 16, 2015 at 02:34:20 AM, Marcel Ziswiler wrote:
On Wed, 2015-08-12 at 13:43 -0500, Andrew Ruder wrote:
Cc: Marek Vasut marex@denx.de Cc: Heiko Schocher hs@denx.de Signed-off-by: Andrew Ruder andrew.ruder@elecsyscorp.com
This driver was written before the driver model stuff was really around (or at least based on a U-Boot version that only had very preliminary support) so there might be some older conventions in use here. I have tested on a PXA270 board running upstream master with this driver, however - so to some extent this all still works fine. Let me know if things need to change to be accepted, and I'll try to find some time to update!
Apart from the missing commit message.
Signed-off-by: Marcel Ziswiler marcel@ziswiler.com
I think you're misunderstanding the meaning of a SoB line here, the SoB line is a certificate of origin. You didn't write the driver and/or you didn't make changes to it, so you don't place your certificate on it :)
Tested-by: Marcel Ziswiler marcel@ziswiler.com
This one is of course good.
Tested-on: Colibri PXA270 V1.2C, V1.2D, V2.2B, V2.4A on Colibri
Is this some kind of a newly invented tag ? :-)
Evaluation Board V3.1A Note: While power I2C works on the older V1.2C version it does not seem to work on any of the newer ones but this might just be a pin muxing resp. missing pull up issue.
Very nice. Btw. how do you bootstrap those modules, do you use that OpenPXA OBM or OBM2 or something else entirely ?
Best regards, Marek Vasut

On Sun, 2015-08-16 at 02:57 +0200, Marek Vasut wrote:
Apart from the missing commit message.
Signed-off-by: Marcel Ziswiler marcel@ziswiler.com
I think you're misunderstanding the meaning of a SoB line here, the SoB line is a certificate of origin. You didn't write the driver and/or you didn't make changes to it, so you don't place your certificate on it :)
Yeah, it's kind of late. Should have been an Acked-by of course, sorry.
Tested-by: Marcel Ziswiler marcel@ziswiler.com
This one is of course good.
Tested-on: Colibri PXA270 V1.2C, V1.2D, V2.2B, V2.4A on Colibri
Is this some kind of a newly invented tag ? :-)
Well, others have been using that one on and off for a while. So at least I am not the inventor (;-p).
Evaluation Board V3.1A Note: While power I2C works on the older V1.2C version it does not
seem
to work on any of the newer ones but this might just be a pin
muxing
resp. missing pull up issue.
Very nice. Btw. how do you bootstrap those modules, do you use that OpenPXA OBM or OBM2 or something else entirely ?
No, I never used any of that crap. Just purely U-Boot even on the PXA3xx but the PXA270 being just a regular NOR beast is really nothing special. Just using ye olde BDI2000 if things go awry. Unfortunately my PXA3xx U-Boot NAND SPL stuff never made it mainline and you since dropped PXA3xx support entirely. If I ever get some precious time I might actually re-add those again especially now with Marvell having committed to keep selling us PXA320 chips to 2020.

On Sunday, August 16, 2015 at 03:13:15 AM, Marcel Ziswiler wrote:
On Sun, 2015-08-16 at 02:57 +0200, Marek Vasut wrote:
Apart from the missing commit message.
Signed-off-by: Marcel Ziswiler marcel@ziswiler.com
I think you're misunderstanding the meaning of a SoB line here, the SoB line is a certificate of origin. You didn't write the driver and/or you didn't make changes to it, so you don't place your certificate on it
:)
Yeah, it's kind of late. Should have been an Acked-by of course, sorry.
I can understand that :)
Tested-by: Marcel Ziswiler marcel@ziswiler.com
This one is of course good.
Tested-on: Colibri PXA270 V1.2C, V1.2D, V2.2B, V2.4A on Colibri
Is this some kind of a newly invented tag ? :-)
Well, others have been using that one on and off for a while. So at least I am not the inventor (;-p).
Heh :)
Evaluation Board V3.1A Note: While power I2C works on the older V1.2C version it does not
seem
to work on any of the newer ones but this might just be a pin
muxing
resp. missing pull up issue.
Very nice. Btw. how do you bootstrap those modules, do you use that OpenPXA OBM or OBM2 or something else entirely ?
No, I never used any of that crap.
Well sorry it wasn't to your liking ... ;-)
Just purely U-Boot even on the PXA3xx but the PXA270 being just a regular NOR beast is really nothing special. Just using ye olde BDI2000 if things go awry. Unfortunately my PXA3xx U-Boot NAND SPL stuff never made it mainline and you since dropped PXA3xx support entirely. If I ever get some precious time I might actually re-add those again especially now with Marvell having committed to keep selling us PXA320 chips to 2020.
There is some very rudimentary SPL support in the u-boot-pxa, but it's really old.
Best regards, Marek Vasut
participants (4)
-
Andrew Ruder
-
Andrew Ruder
-
Marcel Ziswiler
-
Marek Vasut