1979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song/* 2979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song * I2C bus driver for CSR SiRFprimaII 3979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song * 4979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. 5979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song * 6979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song * Licensed under GPLv2 or later. 7979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song */ 8979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 9979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#include <linux/interrupt.h> 10979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#include <linux/kernel.h> 11979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#include <linux/module.h> 12979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#include <linux/slab.h> 13979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#include <linux/platform_device.h> 14979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#include <linux/i2c.h> 15979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#include <linux/clk.h> 16979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#include <linux/err.h> 17979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#include <linux/io.h> 18979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 19979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_CLK_CTRL 0x00 20979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_STATUS 0x0C 21979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_CTRL 0x10 22979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_IO_CTRL 0x14 23979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_SDA_DELAY 0x18 24979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_CMD_START 0x1C 25979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_CMD_BUF 0x30 26979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_DATA_BUF 0x80 27979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 28979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_CMD_BUF_MAX 16 29979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_DATA_BUF_MAX 16 30979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 31979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_CMD(x) (SIRFSOC_I2C_CMD_BUF + (x)*0x04) 32979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_DATA_MASK(x) (0xFF<<(((x)&3)*8)) 33979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_DATA_SHIFT(x) (((x)&3)*8) 34979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 35979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_DIV_MASK (0xFFFF) 36979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 37979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song/* I2C status flags */ 38979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_STAT_BUSY BIT(0) 39979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_STAT_TIP BIT(1) 40979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_STAT_NACK BIT(2) 41979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_STAT_TR_INT BIT(4) 42979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_STAT_STOP BIT(6) 43979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_STAT_CMD_DONE BIT(8) 44979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_STAT_ERR BIT(9) 45979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_CMD_INDEX (0x1F<<16) 46979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 47979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song/* I2C control flags */ 48979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_RESET BIT(0) 49979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_CORE_EN BIT(1) 50979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_MASTER_MODE BIT(2) 51979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_CMD_DONE_EN BIT(11) 52979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_ERR_INT_EN BIT(12) 53979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 54979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_SDA_DELAY_MASK (0xFF) 55979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_SCLF_FILTER (3<<8) 56979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 57979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_START_CMD BIT(0) 58979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 59979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_CMD_RP(x) ((x)&0x7) 60979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_NACK BIT(3) 61979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_WRITE BIT(4) 62979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_READ BIT(5) 63979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_STOP BIT(6) 64979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_START BIT(7) 65979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 66979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#define SIRFSOC_I2C_DEFAULT_SPEED 100000 67979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 68979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstruct sirfsoc_i2c { 69979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song void __iomem *base; 70979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct clk *clk; 71979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song u32 cmd_ptr; /* Current position in CMD buffer */ 72979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song u8 *buf; /* Buffer passed by user */ 73979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song u32 msg_len; /* Message length */ 74979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song u32 finished_len; /* number of bytes read/written */ 75979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song u32 read_cmd_len; /* number of read cmd sent */ 76979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song int msg_read; /* 1 indicates a read message */ 77979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song int err_status; /* 1 indicates an error on bus */ 78979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 79979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song u32 sda_delay; /* For suspend/resume */ 80979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song u32 clk_div; 81979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song int last; /* Last message in transfer, STOP cmd can be sent */ 82979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 83979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct completion done; /* indicates completion of message transfer */ 84979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct i2c_adapter adapter; 85979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song}; 86979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 87979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic void i2c_sirfsoc_read_data(struct sirfsoc_i2c *siic) 88979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song{ 89979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song u32 data = 0; 90979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song int i; 91979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 92979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song for (i = 0; i < siic->read_cmd_len; i++) { 93979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (!(i & 0x3)) 94979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song data = readl(siic->base + SIRFSOC_I2C_DATA_BUF + i); 95979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->buf[siic->finished_len++] = 96979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song (u8)((data & SIRFSOC_I2C_DATA_MASK(i)) >> 97979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song SIRFSOC_I2C_DATA_SHIFT(i)); 98979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 99979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song} 100979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 101979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic void i2c_sirfsoc_queue_cmd(struct sirfsoc_i2c *siic) 102979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song{ 103979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song u32 regval; 104979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song int i = 0; 105979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 106979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (siic->msg_read) { 107979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song while (((siic->finished_len + i) < siic->msg_len) 108979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song && (siic->cmd_ptr < SIRFSOC_I2C_CMD_BUF_MAX)) { 109979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song regval = SIRFSOC_I2C_READ | SIRFSOC_I2C_CMD_RP(0); 110979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (((siic->finished_len + i) == 111979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song (siic->msg_len - 1)) && siic->last) 112979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song regval |= SIRFSOC_I2C_STOP | SIRFSOC_I2C_NACK; 113979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(regval, 114979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); 115979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song i++; 116979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 117979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 118979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->read_cmd_len = i; 119979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } else { 120979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song while ((siic->cmd_ptr < SIRFSOC_I2C_CMD_BUF_MAX - 1) 121979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song && (siic->finished_len < siic->msg_len)) { 122979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song regval = SIRFSOC_I2C_WRITE | SIRFSOC_I2C_CMD_RP(0); 123979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if ((siic->finished_len == (siic->msg_len - 1)) 124979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song && siic->last) 125979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song regval |= SIRFSOC_I2C_STOP; 126979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(regval, 127979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); 128979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(siic->buf[siic->finished_len++], 129979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); 130979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 131979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 132979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->cmd_ptr = 0; 133979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 134979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song /* Trigger the transfer */ 135979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(SIRFSOC_I2C_START_CMD, siic->base + SIRFSOC_I2C_CMD_START); 136979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song} 137979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 138979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic irqreturn_t i2c_sirfsoc_irq(int irq, void *dev_id) 139979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song{ 140979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct sirfsoc_i2c *siic = (struct sirfsoc_i2c *)dev_id; 141979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song u32 i2c_stat = readl(siic->base + SIRFSOC_I2C_STATUS); 142979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 143979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (i2c_stat & SIRFSOC_I2C_STAT_ERR) { 144979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song /* Error conditions */ 145979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->err_status = 1; 146979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(SIRFSOC_I2C_STAT_ERR, siic->base + SIRFSOC_I2C_STATUS); 147979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 148979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (i2c_stat & SIRFSOC_I2C_STAT_NACK) 149979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song dev_err(&siic->adapter.dev, "ACK not received\n"); 150979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song else 151979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song dev_err(&siic->adapter.dev, "I2C error\n"); 152979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 153979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song complete(&siic->done); 154979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } else if (i2c_stat & SIRFSOC_I2C_STAT_CMD_DONE) { 155979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song /* CMD buffer execution complete */ 156979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (siic->msg_read) 157979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song i2c_sirfsoc_read_data(siic); 158979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (siic->finished_len == siic->msg_len) 159979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song complete(&siic->done); 160979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song else /* Fill a new CMD buffer for left data */ 161979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song i2c_sirfsoc_queue_cmd(siic); 162979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 163979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(SIRFSOC_I2C_STAT_CMD_DONE, siic->base + SIRFSOC_I2C_STATUS); 164979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 165979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 166979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song return IRQ_HANDLED; 167979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song} 168979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 169979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic void i2c_sirfsoc_set_address(struct sirfsoc_i2c *siic, 170979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct i2c_msg *msg) 171979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song{ 172979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song unsigned char addr; 173979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song u32 regval = SIRFSOC_I2C_START | SIRFSOC_I2C_CMD_RP(0) | SIRFSOC_I2C_WRITE; 174979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 175979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song /* no data and last message -> add STOP */ 176979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (siic->last && (msg->len == 0)) 177979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song regval |= SIRFSOC_I2C_STOP; 178979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 179979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(regval, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); 180979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 181979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song addr = msg->addr << 1; /* Generate address */ 182979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (msg->flags & I2C_M_RD) 183979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song addr |= 1; 184979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 185979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(addr, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); 186979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song} 187979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 188979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg) 189979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song{ 190979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song u32 regval = readl(siic->base + SIRFSOC_I2C_CTRL); 191979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song /* timeout waiting for the xfer to finish or fail */ 192979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song int timeout = msecs_to_jiffies((msg->len + 1) * 50); 193979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song int ret = 0; 194979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 195979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song i2c_sirfsoc_set_address(siic, msg); 196979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 197979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(regval | SIRFSOC_I2C_CMD_DONE_EN | SIRFSOC_I2C_ERR_INT_EN, 198979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->base + SIRFSOC_I2C_CTRL); 199979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song i2c_sirfsoc_queue_cmd(siic); 200979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 201979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (wait_for_completion_timeout(&siic->done, timeout) == 0) { 202979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->err_status = 1; 203979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song dev_err(&siic->adapter.dev, "Transfer timeout\n"); 204979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 205979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 206979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(regval & ~(SIRFSOC_I2C_CMD_DONE_EN | SIRFSOC_I2C_ERR_INT_EN), 207979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->base + SIRFSOC_I2C_CTRL); 208979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(0, siic->base + SIRFSOC_I2C_CMD_START); 209979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 210979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (siic->err_status) { 211979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET, 212979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->base + SIRFSOC_I2C_CTRL); 213979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) 214979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song cpu_relax(); 215979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 216979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song ret = -EIO; 217979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 218979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 219979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song return ret; 220979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song} 221979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 222979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic u32 i2c_sirfsoc_func(struct i2c_adapter *adap) 223979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song{ 224979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 225979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song} 226979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 227979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic int i2c_sirfsoc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, 228979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song int num) 229979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song{ 230979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct sirfsoc_i2c *siic = adap->algo_data; 231979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song int i, ret; 232979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 233979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk_enable(siic->clk); 234979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 235979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song for (i = 0; i < num; i++) { 236979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->buf = msgs[i].buf; 237979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->msg_len = msgs[i].len; 238979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->msg_read = !!(msgs[i].flags & I2C_M_RD); 239979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->err_status = 0; 240979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->cmd_ptr = 0; 241979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->finished_len = 0; 242979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->last = (i == (num - 1)); 243979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 244979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song ret = i2c_sirfsoc_xfer_msg(siic, &msgs[i]); 245979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (ret) { 246979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk_disable(siic->clk); 247979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song return ret; 248979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 249979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 250979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 251979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk_disable(siic->clk); 252979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song return num; 253979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song} 254979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 255979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song/* I2C algorithms associated with this master controller driver */ 256979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic const struct i2c_algorithm i2c_sirfsoc_algo = { 257979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song .master_xfer = i2c_sirfsoc_xfer, 258979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song .functionality = i2c_sirfsoc_func, 259979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song}; 260979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 261979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic int __devinit i2c_sirfsoc_probe(struct platform_device *pdev) 262979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song{ 263979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct sirfsoc_i2c *siic; 264979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct i2c_adapter *adap; 265979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct resource *mem_res; 266979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct clk *clk; 267979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song int bitrate; 268979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song int ctrl_speed; 269979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song int irq; 270979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 271979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song int err; 272979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song u32 regval; 273979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 274979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk = clk_get(&pdev->dev, NULL); 275979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (IS_ERR(clk)) { 276979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song err = PTR_ERR(clk); 277979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song dev_err(&pdev->dev, "Clock get failed\n"); 278979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song goto err_get_clk; 279979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 280979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 281979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song err = clk_prepare(clk); 282979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (err) { 283979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song dev_err(&pdev->dev, "Clock prepare failed\n"); 284979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song goto err_clk_prep; 285979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 286979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 287979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song err = clk_enable(clk); 288979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (err) { 289979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song dev_err(&pdev->dev, "Clock enable failed\n"); 290979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song goto err_clk_en; 291979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 292979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 293979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song ctrl_speed = clk_get_rate(clk); 294979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 295979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic = devm_kzalloc(&pdev->dev, sizeof(*siic), GFP_KERNEL); 296979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (!siic) { 297979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song dev_err(&pdev->dev, "Can't allocate driver data\n"); 298979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song err = -ENOMEM; 299979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song goto out; 300979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 301979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song adap = &siic->adapter; 302979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song adap->class = I2C_CLASS_HWMON; 303979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 304979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 305979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (mem_res == NULL) { 306979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song dev_err(&pdev->dev, "Unable to get MEM resource\n"); 307979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song err = -EINVAL; 308979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song goto out; 309979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 310979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 311979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->base = devm_request_and_ioremap(&pdev->dev, mem_res); 312979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (siic->base == NULL) { 313979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song dev_err(&pdev->dev, "IO remap failed!\n"); 314979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song err = -ENOMEM; 315979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song goto out; 316979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 317979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 318979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song irq = platform_get_irq(pdev, 0); 319979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (irq < 0) { 320979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song err = irq; 321979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song goto out; 322979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 323979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song err = devm_request_irq(&pdev->dev, irq, i2c_sirfsoc_irq, 0, 324979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song dev_name(&pdev->dev), siic); 325979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (err) 326979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song goto out; 327979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 328979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song adap->algo = &i2c_sirfsoc_algo; 329979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song adap->algo_data = siic; 330979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 331979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song adap->dev.parent = &pdev->dev; 332979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song adap->nr = pdev->id; 333979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 334979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song strlcpy(adap->name, "sirfsoc-i2c", sizeof(adap->name)); 335979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 336979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song platform_set_drvdata(pdev, adap); 337979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song init_completion(&siic->done); 338979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 339979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song /* Controller Initalisation */ 340979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 341979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL); 342979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) 343979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song cpu_relax(); 344979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(SIRFSOC_I2C_CORE_EN | SIRFSOC_I2C_MASTER_MODE, 345979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->base + SIRFSOC_I2C_CTRL); 346979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 347979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->clk = clk; 348979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 349979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song err = of_property_read_u32(pdev->dev.of_node, 350979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song "clock-frequency", &bitrate); 351979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (err < 0) 352979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song bitrate = SIRFSOC_I2C_DEFAULT_SPEED; 353979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 354979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (bitrate < 100000) 355979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song regval = 356979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song (2 * ctrl_speed) / (2 * bitrate * 11); 357979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song else 358979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song regval = ctrl_speed / (bitrate * 5); 359979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 360979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(regval, siic->base + SIRFSOC_I2C_CLK_CTRL); 361979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (regval > 0xFF) 362979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(0xFF, siic->base + SIRFSOC_I2C_SDA_DELAY); 363979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song else 364979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(regval, siic->base + SIRFSOC_I2C_SDA_DELAY); 365979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 366979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song err = i2c_add_numbered_adapter(adap); 367979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song if (err < 0) { 368979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song dev_err(&pdev->dev, "Can't add new i2c adapter\n"); 369979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song goto out; 370979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song } 371979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 372979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk_disable(clk); 373979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 374979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song dev_info(&pdev->dev, " I2C adapter ready to operate\n"); 375979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 376979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song return 0; 377979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 378979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songout: 379979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk_disable(clk); 380979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songerr_clk_en: 381979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk_unprepare(clk); 382979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songerr_clk_prep: 383979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk_put(clk); 384979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songerr_get_clk: 385979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song return err; 386979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song} 387979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 388979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic int __devexit i2c_sirfsoc_remove(struct platform_device *pdev) 389979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song{ 390979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct i2c_adapter *adapter = platform_get_drvdata(pdev); 391979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct sirfsoc_i2c *siic = adapter->algo_data; 392979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 393979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL); 394979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song i2c_del_adapter(adapter); 395979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk_unprepare(siic->clk); 396979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk_put(siic->clk); 397979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song return 0; 398979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song} 399979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 400979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#ifdef CONFIG_PM 401979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic int i2c_sirfsoc_suspend(struct device *dev) 402979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song{ 403979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct platform_device *pdev = to_platform_device(dev); 404979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct i2c_adapter *adapter = platform_get_drvdata(pdev); 405979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct sirfsoc_i2c *siic = adapter->algo_data; 406979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 407979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk_enable(siic->clk); 408979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->sda_delay = readl(siic->base + SIRFSOC_I2C_SDA_DELAY); 409979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->clk_div = readl(siic->base + SIRFSOC_I2C_CLK_CTRL); 410979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk_disable(siic->clk); 411979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song return 0; 412979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song} 413979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 414979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic int i2c_sirfsoc_resume(struct device *dev) 415979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song{ 416979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct platform_device *pdev = to_platform_device(dev); 417979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct i2c_adapter *adapter = platform_get_drvdata(pdev); 418979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song struct sirfsoc_i2c *siic = adapter->algo_data; 419979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 420979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk_enable(siic->clk); 421979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL); 422979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(SIRFSOC_I2C_CORE_EN | SIRFSOC_I2C_MASTER_MODE, 423979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song siic->base + SIRFSOC_I2C_CTRL); 424979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(siic->clk_div, siic->base + SIRFSOC_I2C_CLK_CTRL); 425979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song writel(siic->sda_delay, siic->base + SIRFSOC_I2C_SDA_DELAY); 426979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song clk_disable(siic->clk); 427979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song return 0; 428979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song} 429979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 430979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic const struct dev_pm_ops i2c_sirfsoc_pm_ops = { 431979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song .suspend = i2c_sirfsoc_suspend, 432979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song .resume = i2c_sirfsoc_resume, 433979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song}; 434979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#endif 435979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 436979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic const struct of_device_id sirfsoc_i2c_of_match[] __devinitconst = { 437979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song { .compatible = "sirf,prima2-i2c", }, 438979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song {}, 439979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song}; 440979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu SongMODULE_DEVICE_TABLE(of, sirfsoc_i2c_of_match); 441979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 442979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songstatic struct platform_driver i2c_sirfsoc_driver = { 443979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song .driver = { 444979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song .name = "sirfsoc_i2c", 445979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song .owner = THIS_MODULE, 446979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#ifdef CONFIG_PM 447979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song .pm = &i2c_sirfsoc_pm_ops, 448979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song#endif 449979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song .of_match_table = sirfsoc_i2c_of_match, 450979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song }, 451979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song .probe = i2c_sirfsoc_probe, 452979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song .remove = __devexit_p(i2c_sirfsoc_remove), 453979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song}; 454979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Songmodule_platform_driver(i2c_sirfsoc_driver); 455979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song 456979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu SongMODULE_DESCRIPTION("SiRF SoC I2C master controller driver"); 457979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu SongMODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>, " 458979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu Song "Xiangzhen Ye <Xiangzhen.Ye@csr.com>"); 459979b907fa55be8cdbbf455b9204b7e4602f303e6Zhiwu SongMODULE_LICENSE("GPL v2"); 460