^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Specific bus support for PMC-TWI compliant implementation on MSP71xx.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright 2005-2007 PMC-Sierra, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This program is free software; you can redistribute it and/or modify it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * under the terms of the GNU General Public License as published by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Free Software Foundation; either version 2 of the License, or (at your
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define DRV_NAME "pmcmsptwi"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define MSP_TWI_SF_CLK_REG_OFFSET 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define MSP_TWI_HS_CLK_REG_OFFSET 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define MSP_TWI_CFG_REG_OFFSET 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MSP_TWI_CMD_REG_OFFSET 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define MSP_TWI_ADD_REG_OFFSET 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define MSP_TWI_DAT_0_REG_OFFSET 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define MSP_TWI_DAT_1_REG_OFFSET 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define MSP_TWI_INT_STS_REG_OFFSET 0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define MSP_TWI_INT_MSK_REG_OFFSET 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define MSP_TWI_BUSY_REG_OFFSET 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define MSP_TWI_INT_STS_DONE (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define MSP_TWI_INT_STS_LOST_ARBITRATION (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define MSP_TWI_INT_STS_NO_RESPONSE (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define MSP_TWI_INT_STS_DATA_COLLISION (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define MSP_TWI_INT_STS_BUSY (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define MSP_TWI_INT_STS_ALL 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define MSP_MAX_BYTES_PER_RW 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define MSP_MAX_POLL 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define MSP_POLL_DELAY 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define MSP_IRQ_TIMEOUT (MSP_MAX_POLL * MSP_POLL_DELAY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* IO Operation macros */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define pmcmsptwi_readl __raw_readl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define pmcmsptwi_writel __raw_writel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* TWI command type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) enum pmcmsptwi_cmd_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) MSP_TWI_CMD_WRITE = 0, /* Write only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) MSP_TWI_CMD_READ = 1, /* Read only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) MSP_TWI_CMD_WRITE_READ = 2, /* Write then Read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* The possible results of the xferCmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) enum pmcmsptwi_xfer_result {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) MSP_TWI_XFER_OK = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) MSP_TWI_XFER_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) MSP_TWI_XFER_BUSY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) MSP_TWI_XFER_DATA_COLLISION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) MSP_TWI_XFER_NO_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) MSP_TWI_XFER_LOST_ARBITRATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* Corresponds to a PMCTWI clock configuration register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct pmcmsptwi_clock {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) u8 filter; /* Bits 15:12, default = 0x03 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) u16 clock; /* Bits 9:0, default = 0x001f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct pmcmsptwi_clockcfg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct pmcmsptwi_clock standard; /* The standard/fast clock config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct pmcmsptwi_clock highspeed; /* The highspeed clock config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* Corresponds to the main TWI configuration register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct pmcmsptwi_cfg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u8 arbf; /* Bits 15:12, default=0x03 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) u8 nak; /* Bits 11:8, default=0x03 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u8 add10; /* Bit 7, default=0x00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u8 mst_code; /* Bits 6:4, default=0x00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) u8 arb; /* Bit 1, default=0x01 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u8 highspeed; /* Bit 0, default=0x00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* A single pmctwi command to issue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct pmcmsptwi_cmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u16 addr; /* The slave address (7 or 10 bits) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) enum pmcmsptwi_cmd_type type; /* The command type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u8 write_len; /* Number of bytes in the write buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u8 read_len; /* Number of bytes in the read buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u8 *write_data; /* Buffer of characters to send */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u8 *read_data; /* Buffer to fill with incoming data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* The private data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct pmcmsptwi_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) void __iomem *iobase; /* iomapped base for IO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int irq; /* IRQ to use (0 disables) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct completion wait; /* Completion for xfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct mutex lock; /* Used for threadsafeness */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) enum pmcmsptwi_xfer_result last_result; /* result of last xfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* The default settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static const struct pmcmsptwi_clockcfg pmcmsptwi_defclockcfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .standard = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .filter = 0x3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .clock = 0x1f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .highspeed = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .filter = 0x3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .clock = 0x1f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static const struct pmcmsptwi_cfg pmcmsptwi_defcfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .arbf = 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .nak = 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .add10 = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .mst_code = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .arb = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .highspeed = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static struct pmcmsptwi_data pmcmsptwi_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static struct i2c_adapter pmcmsptwi_adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* inline helper functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static inline u32 pmcmsptwi_clock_to_reg(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) const struct pmcmsptwi_clock *clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return ((clock->filter & 0xf) << 12) | (clock->clock & 0x03ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static inline u32 pmcmsptwi_cfg_to_reg(const struct pmcmsptwi_cfg *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return ((cfg->arbf & 0xf) << 12) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ((cfg->nak & 0xf) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ((cfg->add10 & 0x1) << 7) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ((cfg->mst_code & 0x7) << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ((cfg->arb & 0x1) << 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) (cfg->highspeed & 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static inline void pmcmsptwi_reg_to_cfg(u32 reg, struct pmcmsptwi_cfg *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) cfg->arbf = (reg >> 12) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) cfg->nak = (reg >> 8) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) cfg->add10 = (reg >> 7) & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) cfg->mst_code = (reg >> 4) & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) cfg->arb = (reg >> 1) & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) cfg->highspeed = reg & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * Sets the current clock configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static void pmcmsptwi_set_clock_config(const struct pmcmsptwi_clockcfg *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct pmcmsptwi_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->standard),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) data->iobase + MSP_TWI_SF_CLK_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->highspeed),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) data->iobase + MSP_TWI_HS_CLK_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * Gets the current TWI bus configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static void pmcmsptwi_get_twi_config(struct pmcmsptwi_cfg *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct pmcmsptwi_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) pmcmsptwi_reg_to_cfg(pmcmsptwi_readl(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) data->iobase + MSP_TWI_CFG_REG_OFFSET), cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * Sets the current TWI bus configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static void pmcmsptwi_set_twi_config(const struct pmcmsptwi_cfg *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct pmcmsptwi_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) pmcmsptwi_writel(pmcmsptwi_cfg_to_reg(cfg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) data->iobase + MSP_TWI_CFG_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * Parses the 'int_sts' register and returns a well-defined error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static enum pmcmsptwi_xfer_result pmcmsptwi_get_result(u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (reg & MSP_TWI_INT_STS_LOST_ARBITRATION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) dev_dbg(&pmcmsptwi_adapter.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) "Result: Lost arbitration\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return MSP_TWI_XFER_LOST_ARBITRATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) } else if (reg & MSP_TWI_INT_STS_NO_RESPONSE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) dev_dbg(&pmcmsptwi_adapter.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) "Result: No response\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return MSP_TWI_XFER_NO_RESPONSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) } else if (reg & MSP_TWI_INT_STS_DATA_COLLISION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) dev_dbg(&pmcmsptwi_adapter.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) "Result: Data collision\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return MSP_TWI_XFER_DATA_COLLISION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) } else if (reg & MSP_TWI_INT_STS_BUSY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) dev_dbg(&pmcmsptwi_adapter.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) "Result: Bus busy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return MSP_TWI_XFER_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) dev_dbg(&pmcmsptwi_adapter.dev, "Result: Operation succeeded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return MSP_TWI_XFER_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * In interrupt mode, handle the interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * NOTE: Assumes data->lock is held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static irqreturn_t pmcmsptwi_interrupt(int irq, void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct pmcmsptwi_data *data = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) u32 reason = pmcmsptwi_readl(data->iobase +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) MSP_TWI_INT_STS_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) pmcmsptwi_writel(reason, data->iobase + MSP_TWI_INT_STS_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) dev_dbg(&pmcmsptwi_adapter.dev, "Got interrupt 0x%08x\n", reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (!(reason & MSP_TWI_INT_STS_DONE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) data->last_result = pmcmsptwi_get_result(reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) complete(&data->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * Probe for and register the device and return 0 if there is one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int pmcmsptwi_probe(struct platform_device *pldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /* get the static platform resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) dev_err(&pldev->dev, "IOMEM resource not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) goto ret_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* reserve the memory region */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (!request_mem_region(res->start, resource_size(res),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) pldev->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dev_err(&pldev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) "Unable to get memory/io address region %pap\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) &res->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) rc = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) goto ret_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* remap the memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) pmcmsptwi_data.iobase = ioremap(res->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (!pmcmsptwi_data.iobase) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) dev_err(&pldev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) "Unable to ioremap address %pap\n", &res->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) goto ret_unreserve;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* request the irq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) pmcmsptwi_data.irq = platform_get_irq(pldev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (pmcmsptwi_data.irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) IRQF_SHARED, pldev->name, &pmcmsptwi_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (rc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * Enable 'DONE' interrupt only.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * If you enable all interrupts, you will get one on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * error and another when the operation completes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * This way you only have to handle one interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * but you can still check all result flags.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) pmcmsptwi_writel(MSP_TWI_INT_STS_DONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) pmcmsptwi_data.iobase +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) MSP_TWI_INT_MSK_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) dev_warn(&pldev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) "Could not assign TWI IRQ handler "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) "to irq %d (continuing with poll)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) pmcmsptwi_data.irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) pmcmsptwi_data.irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) init_completion(&pmcmsptwi_data.wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) mutex_init(&pmcmsptwi_data.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) pmcmsptwi_set_clock_config(&pmcmsptwi_defclockcfg, &pmcmsptwi_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) pmcmsptwi_set_twi_config(&pmcmsptwi_defcfg, &pmcmsptwi_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) printk(KERN_INFO DRV_NAME ": Registering MSP71xx I2C adapter\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) pmcmsptwi_adapter.dev.parent = &pldev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) platform_set_drvdata(pldev, &pmcmsptwi_adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) i2c_set_adapdata(&pmcmsptwi_adapter, &pmcmsptwi_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) rc = i2c_add_adapter(&pmcmsptwi_adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) goto ret_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) ret_unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (pmcmsptwi_data.irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) pmcmsptwi_writel(0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) iounmap(pmcmsptwi_data.iobase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) ret_unreserve:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) release_mem_region(res->start, resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) ret_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * Release the device and return 0 if there is one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static int pmcmsptwi_remove(struct platform_device *pldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) i2c_del_adapter(&pmcmsptwi_adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (pmcmsptwi_data.irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) pmcmsptwi_writel(0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) iounmap(pmcmsptwi_data.iobase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) release_mem_region(res->start, resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * Polls the 'busy' register until the command is complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * NOTE: Assumes data->lock is held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static void pmcmsptwi_poll_complete(struct pmcmsptwi_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) for (i = 0; i < MSP_MAX_POLL; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) u32 val = pmcmsptwi_readl(data->iobase +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) MSP_TWI_BUSY_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (val == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) u32 reason = pmcmsptwi_readl(data->iobase +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) MSP_TWI_INT_STS_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) pmcmsptwi_writel(reason, data->iobase +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) MSP_TWI_INT_STS_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) data->last_result = pmcmsptwi_get_result(reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) udelay(MSP_POLL_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) dev_dbg(&pmcmsptwi_adapter.dev, "Result: Poll timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) data->last_result = MSP_TWI_XFER_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * Do the transfer (low level):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * May use interrupt-driven or polling, depending on if an IRQ is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * presently registered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * NOTE: Assumes data->lock is held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static enum pmcmsptwi_xfer_result pmcmsptwi_do_xfer(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) u32 reg, struct pmcmsptwi_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) dev_dbg(&pmcmsptwi_adapter.dev, "Writing cmd reg 0x%08x\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) pmcmsptwi_writel(reg, data->iobase + MSP_TWI_CMD_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (data->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) unsigned long timeleft = wait_for_completion_timeout(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) &data->wait, MSP_IRQ_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (timeleft == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) dev_dbg(&pmcmsptwi_adapter.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) "Result: IRQ timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) complete(&data->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) data->last_result = MSP_TWI_XFER_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) pmcmsptwi_poll_complete(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return data->last_result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * Helper routine, converts 'pmctwi_cmd' struct to register format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) static inline u32 pmcmsptwi_cmd_to_reg(const struct pmcmsptwi_cmd *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) return ((cmd->type & 0x3) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) (((cmd->write_len - 1) & 0x7) << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) ((cmd->read_len - 1) & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * Do the transfer (high level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct pmcmsptwi_cmd *cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) struct pmcmsptwi_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) enum pmcmsptwi_xfer_result retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) dev_dbg(&pmcmsptwi_adapter.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) "Setting address to 0x%04x\n", cmd->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) pmcmsptwi_writel(cmd->addr, data->iobase + MSP_TWI_ADD_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (cmd->type == MSP_TWI_CMD_WRITE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) cmd->type == MSP_TWI_CMD_WRITE_READ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) u64 tmp = be64_to_cpup((__be64 *)cmd->write_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) tmp >>= (MSP_MAX_BYTES_PER_RW - cmd->write_len) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) dev_dbg(&pmcmsptwi_adapter.dev, "Writing 0x%016llx\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) pmcmsptwi_writel(tmp & 0x00000000ffffffffLL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) data->iobase + MSP_TWI_DAT_0_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (cmd->write_len > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) pmcmsptwi_writel(tmp >> 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) data->iobase + MSP_TWI_DAT_1_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) retval = pmcmsptwi_do_xfer(pmcmsptwi_cmd_to_reg(cmd), data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (retval != MSP_TWI_XFER_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) goto xfer_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (cmd->type == MSP_TWI_CMD_READ ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) cmd->type == MSP_TWI_CMD_WRITE_READ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) u64 rmsk = ~(0xffffffffffffffffLL << (cmd->read_len * 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) u64 tmp = (u64)pmcmsptwi_readl(data->iobase +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) MSP_TWI_DAT_0_REG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (cmd->read_len > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) tmp |= (u64)pmcmsptwi_readl(data->iobase +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) MSP_TWI_DAT_1_REG_OFFSET) << 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) tmp &= rmsk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) dev_dbg(&pmcmsptwi_adapter.dev, "Read 0x%016llx\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) for (i = 0; i < cmd->read_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) cmd->read_data[i] = tmp >> i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) xfer_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /* -- Algorithm functions -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * Sends an i2c command out on the adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) static int pmcmsptwi_master_xfer(struct i2c_adapter *adap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct i2c_msg *msg, int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct pmcmsptwi_data *data = i2c_get_adapdata(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct pmcmsptwi_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct pmcmsptwi_cfg oldcfg, newcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (num == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) struct i2c_msg *nextmsg = msg + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) cmd.type = MSP_TWI_CMD_WRITE_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) cmd.write_len = msg->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) cmd.write_data = msg->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) cmd.read_len = nextmsg->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) cmd.read_data = nextmsg->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) } else if (msg->flags & I2C_M_RD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) cmd.type = MSP_TWI_CMD_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) cmd.read_len = msg->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) cmd.read_data = msg->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) cmd.write_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) cmd.write_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) cmd.type = MSP_TWI_CMD_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) cmd.read_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) cmd.read_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) cmd.write_len = msg->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) cmd.write_data = msg->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) cmd.addr = msg->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (msg->flags & I2C_M_TEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) pmcmsptwi_get_twi_config(&newcfg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) memcpy(&oldcfg, &newcfg, sizeof(oldcfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* Set the special 10-bit address flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) newcfg.add10 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) pmcmsptwi_set_twi_config(&newcfg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /* Execute the command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) ret = pmcmsptwi_xfer_cmd(&cmd, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (msg->flags & I2C_M_TEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) pmcmsptwi_set_twi_config(&oldcfg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) dev_dbg(&adap->dev, "I2C %s of %d bytes %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) (msg->flags & I2C_M_RD) ? "read" : "write", msg->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) (ret == MSP_TWI_XFER_OK) ? "succeeded" : "failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (ret != MSP_TWI_XFER_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * TODO: We could potentially loop and retry in the case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * of MSP_TWI_XFER_TIMEOUT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) static const struct i2c_adapter_quirks pmcmsptwi_i2c_quirks = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) .flags = I2C_AQ_COMB_WRITE_THEN_READ | I2C_AQ_NO_ZERO_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) .max_write_len = MSP_MAX_BYTES_PER_RW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) .max_read_len = MSP_MAX_BYTES_PER_RW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) .max_comb_1st_msg_len = MSP_MAX_BYTES_PER_RW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) .max_comb_2nd_msg_len = MSP_MAX_BYTES_PER_RW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) /* -- Initialization -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) static const struct i2c_algorithm pmcmsptwi_algo = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) .master_xfer = pmcmsptwi_master_xfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) .functionality = pmcmsptwi_i2c_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) static struct i2c_adapter pmcmsptwi_adapter = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) .algo = &pmcmsptwi_algo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) .quirks = &pmcmsptwi_i2c_quirks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) .name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static struct platform_driver pmcmsptwi_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) .probe = pmcmsptwi_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) .remove = pmcmsptwi_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) .name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) module_platform_driver(pmcmsptwi_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) MODULE_DESCRIPTION("PMC MSP TWI/SMBus/I2C driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) MODULE_ALIAS("platform:" DRV_NAME);