Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);