update to 9f12731260

1.dts:ls2k300:Correct label of spi
2.ls2k300:Add a defconfig for rt
3.fix SD-card CMD48 stuck
4.fix i2c hang  when touch for a long time
This commit is contained in:
maoxiaochuan
2025-03-26 13:04:16 +08:00
parent 7bd1154c2e
commit ff60a514ff
10 changed files with 1149 additions and 302 deletions
+329 -297
View File
@@ -23,49 +23,49 @@
#include <linux/reset.h>
/* Loongson I2C offset registers */
#define I2C_CR1 0x00
#define I2C_CR2 0x04
#define I2C_DR 0x10
#define I2C_SR1 0x14
#define I2C_SR2 0x18
#define I2C_CCR 0x1C
#define I2C_TRISE 0x20
#define I2C_FLTR 0x24
#define I2C_CR1 0x00
#define I2C_CR2 0x04
#define I2C_DR 0x10
#define I2C_SR1 0x14
#define I2C_SR2 0x18
#define I2C_CCR 0x1C
#define I2C_TRISE 0x20
#define I2C_FLTR 0x24
/* Loongson I2C control 1*/
#define I2C_CR1_POS BIT(11)
#define I2C_CR1_ACK BIT(10)
#define I2C_CR1_STOP BIT(9)
#define I2C_CR1_START BIT(8)
#define I2C_CR1_PE BIT(0)
#define I2C_CR1_POS BIT(11)
#define I2C_CR1_ACK BIT(10)
#define I2C_CR1_STOP BIT(9)
#define I2C_CR1_START BIT(8)
#define I2C_CR1_PE BIT(0)
/* Loongson I2C control 2 */
#define I2C_CR2_FREQ_MASK GENMASK(5, 0)
#define I2C_CR2_FREQ(n) ((n) & I2C_CR2_FREQ_MASK)
#define I2C_CR2_ITBUFEN BIT(10)
#define I2C_CR2_ITEVTEN BIT(9)
#define I2C_CR2_ITERREN BIT(8)
#define I2C_CR2_IRQ_MASK (I2C_CR2_ITBUFEN | \
I2C_CR2_ITEVTEN | \
I2C_CR2_ITERREN)
#define I2C_CR2_FREQ_MASK GENMASK(5, 0)
#define I2C_CR2_FREQ(n) ((n) & I2C_CR2_FREQ_MASK)
#define I2C_CR2_ITBUFEN BIT(10)
#define I2C_CR2_ITEVTEN BIT(9)
#define I2C_CR2_ITERREN BIT(8)
#define I2C_CR2_IRQ_MASK (I2C_CR2_ITBUFEN | \
I2C_CR2_ITEVTEN | \
I2C_CR2_ITERREN)
/* Loongson I2C Status 1 */
#define I2C_SR1_AF BIT(10)
#define I2C_SR1_ARLO BIT(9)
#define I2C_SR1_BERR BIT(8)
#define I2C_SR1_TXE BIT(7)
#define I2C_SR1_RXNE BIT(6)
#define I2C_SR1_BTF BIT(2)
#define I2C_SR1_ADDR BIT(1)
#define I2C_SR1_SB BIT(0)
#define I2C_SR1_ITEVTEN_MASK (I2C_SR1_BTF | \
I2C_SR1_ADDR | \
I2C_SR1_SB)
#define I2C_SR1_ITBUFEN_MASK (I2C_SR1_TXE | \
I2C_SR1_RXNE)
#define I2C_SR1_ITERREN_MASK (I2C_SR1_AF | \
I2C_SR1_ARLO | \
I2C_SR1_BERR)
#define I2C_SR1_AF BIT(10)
#define I2C_SR1_ARLO BIT(9)
#define I2C_SR1_BERR BIT(8)
#define I2C_SR1_TXE BIT(7)
#define I2C_SR1_RXNE BIT(6)
#define I2C_SR1_BTF BIT(2)
#define I2C_SR1_ADDR BIT(1)
#define I2C_SR1_SB BIT(0)
#define I2C_SR1_ITEVTEN_MASK (I2C_SR1_BTF | \
I2C_SR1_ADDR | \
I2C_SR1_SB)
#define I2C_SR1_ITBUFEN_MASK (I2C_SR1_TXE | \
I2C_SR1_RXNE)
#define I2C_SR1_ITERREN_MASK (I2C_SR1_AF | \
I2C_SR1_ARLO | \
I2C_SR1_BERR)
/* Loongson I2C Status 2 */
#define I2C_SR2_BUSY BIT(1)
@@ -103,6 +103,7 @@ struct priv_msg {
* @complete: completion of I2C message
* @speed: Standard or Fast are supported
* @msg: I2C transfer information
* @freq: I2C controller input clock freq
*/
struct ls_i2c_dev {
struct i2c_adapter adap;
@@ -111,6 +112,7 @@ struct ls_i2c_dev {
struct completion complete;
int speed;
struct priv_msg msg;
int freq;
};
static inline void i2c_set_bits(void __iomem *reg, u32 mask)
@@ -130,7 +132,7 @@ static void ls_i2c_disable_irq(struct ls_i2c_dev *i2c_dev)
i2c_clr_bits(reg, I2C_CR2_IRQ_MASK);
}
#define INPUT_REF_CLK 120000000
#define INPUT_DEFAULT_CLK 200000000
static int ls_i2c_hw_config(struct ls_i2c_dev *i2c_dev)
{
@@ -142,9 +144,9 @@ static int ls_i2c_hw_config(struct ls_i2c_dev *i2c_dev)
i2c_set_bits(i2c_dev->base + I2C_TRISE, 0x3f);
if (i2c_dev->speed == LS_I2C_SPEED_STANDARD) {
val = DIV_ROUND_UP(INPUT_REF_CLK, 100000 * 2);
val = DIV_ROUND_UP(i2c_dev->freq, 100000 * 2);
} else {
val = DIV_ROUND_UP(INPUT_REF_CLK, 400000 * 3);
val = DIV_ROUND_UP(i2c_dev->freq, 400000 * 3);
/* Select Fast mode */
ccr |= I2C_CCR_FS;
@@ -164,9 +166,9 @@ static int ls_i2c_wait_free_bus(struct ls_i2c_dev *i2c_dev)
int ret;
ret = readl_poll_timeout(i2c_dev->base + I2C_SR2,
status,
!(status & I2C_SR2_BUSY),
10, 1000);
status,
!(status & I2C_SR2_BUSY),
10, 2000);
if (ret) {
dev_dbg(i2c_dev->dev, "bus not free\n");
ret = -EBUSY;
@@ -175,262 +177,280 @@ static int ls_i2c_wait_free_bus(struct ls_i2c_dev *i2c_dev)
return ret;
}
static void ls_i2c_write_byte(struct ls_i2c_dev *i2c_dev, u8 byte)
static int i2c_wait_EV_signal(struct ls_i2c_dev *i2c_dev, int reg, int mask, int target)
{
writel(byte, i2c_dev->base + I2C_DR);
}
static void ls_i2c_read_msg(struct ls_i2c_dev *i2c_dev)
{
struct priv_msg *msg = &i2c_dev->msg;
*msg->buf++ = readl(i2c_dev->base + I2C_DR);
msg->count--;
}
static void ls_i2c_terminate_xfer(struct ls_i2c_dev *i2c_dev)
{
struct priv_msg *msg = &i2c_dev->msg;
ls_i2c_disable_irq(i2c_dev);
i2c_set_bits(i2c_dev->base + I2C_CR1, (1 << (8 + msg->stop)));
complete(&i2c_dev->complete);
}
static void ls_i2c_handle_write(struct ls_i2c_dev *i2c_dev)
{
struct priv_msg *msg = &i2c_dev->msg;
void __iomem *reg = i2c_dev->base + I2C_CR2;
if (msg->count) {
ls_i2c_write_byte(i2c_dev, *msg->buf++);
msg->count--;
if (!msg->count)
i2c_clr_bits(reg, I2C_CR2_ITBUFEN);
} else {
ls_i2c_terminate_xfer(i2c_dev);
}
}
static void ls_i2c_handle_read(struct ls_i2c_dev *i2c_dev, int flag)
{
struct priv_msg *msg = &i2c_dev->msg;
void __iomem *reg = i2c_dev->base + I2C_CR2;
int i;
switch (msg->count) {
case 1:
/* only transmit 1 bytes condition */
ls_i2c_disable_irq(i2c_dev);
ls_i2c_read_msg(i2c_dev);
complete(&i2c_dev->complete);
break;
case 2:
if (flag != 1) {
/* ensure only transmit 2 bytes condition */
i2c_clr_bits(reg, I2C_CR2_ITBUFEN);
break;
}
i2c_set_bits(i2c_dev->base + I2C_CR1, (1 << (8 + msg->stop)));
ls_i2c_disable_irq(i2c_dev);
for (i = 2; i > 0; i--)
ls_i2c_read_msg(i2c_dev);
i2c_clr_bits(i2c_dev->base + I2C_CR1, I2C_CR1_POS);
complete(&i2c_dev->complete);
break;
case 3:
if (readl(i2c_dev->base + I2C_CR2) & I2C_CR2_ITBUFEN) {
i2c_clr_bits(reg, I2C_CR2_ITBUFEN);
break;
}
reg = i2c_dev->base + I2C_CR1;
i2c_clr_bits(reg, I2C_CR1_ACK);
fallthrough;
default:
ls_i2c_read_msg(i2c_dev);
}
}
/**
* ls_i2c_handle_rx_addr()
* master receiver
* @i2c_dev: Controller's private data
*/
static void ls_i2c_handle_rx_addr(struct ls_i2c_dev *i2c_dev)
{
struct priv_msg *msg = &i2c_dev->msg;
switch (msg->count) {
case 0:
ls_i2c_terminate_xfer(i2c_dev);
break;
case 1:
i2c_clr_bits(i2c_dev->base + I2C_CR1,
(I2C_CR1_ACK | I2C_CR1_POS));
/* start or stop */
i2c_set_bits(i2c_dev->base + I2C_CR1, (1 << (8 + msg->stop)));
break;
case 2:
i2c_clr_bits(i2c_dev->base + I2C_CR1, I2C_CR1_ACK);
i2c_set_bits(i2c_dev->base + I2C_CR1, I2C_CR1_POS);
break;
default:
i2c_set_bits(i2c_dev->base + I2C_CR1, I2C_CR1_ACK);
i2c_clr_bits(i2c_dev->base + I2C_CR1, I2C_CR1_POS);
break;
}
}
static irqreturn_t ls_i2c_isr_error(u32 status, void *data)
{
struct ls_i2c_dev *i2c_dev = data;
struct priv_msg *msg = &i2c_dev->msg;
/* Arbitration lost */
if (status & I2C_SR1_ARLO) {
i2c_clr_bits(i2c_dev->base + I2C_SR1, I2C_SR1_ARLO);
msg->result = -EAGAIN;
}
/*
* Acknowledge failure:
* In master transmitter mode a Stop must be generated by software
*/
if (status & I2C_SR1_AF) {
i2c_set_bits(i2c_dev->base + I2C_CR1, I2C_CR1_STOP);
i2c_clr_bits(i2c_dev->base + I2C_SR1, I2C_SR1_AF);
msg->result = -EIO;
}
/* Bus error */
if (status & I2C_SR1_BERR) {
i2c_clr_bits(i2c_dev->base + I2C_SR1, I2C_SR1_BERR);
msg->result = -EIO;
}
ls_i2c_disable_irq(i2c_dev);
complete(&i2c_dev->complete);
return IRQ_HANDLED;
}
/**
* ls_i2c_isr_event() - Interrupt routine for I2C bus event
* @irq: interrupt number
* @data: Controller's private data
*/
static irqreturn_t ls_i2c_isr_event(int irq, void *data)
{
struct ls_i2c_dev *i2c_dev = data;
struct priv_msg *msg = &i2c_dev->msg;
u32 status, ien, event, cr2;
u32 possible_status = I2C_SR1_ITEVTEN_MASK;
int i;
status = readl(i2c_dev->base + I2C_SR1);
if (status & (I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_BERR))
return ls_i2c_isr_error(status, data);
cr2 = readl(i2c_dev->base + I2C_CR2);
ien = cr2 & I2C_CR2_IRQ_MASK;
/* Update possible_status if buffer interrupt is enabled */
if (ien & I2C_CR2_ITBUFEN)
possible_status |= I2C_SR1_ITBUFEN_MASK;
event = status & possible_status;
if (!event) {
dev_dbg(i2c_dev->dev,
"spurious evt irq (status=0x%08x, ien=0x%08x)\n",
status, ien);
return IRQ_NONE;
}
/* Start condition generated */
if (event & I2C_SR1_SB)
ls_i2c_write_byte(i2c_dev, msg->addr);
/* I2C Address sent */
if (event & I2C_SR1_ADDR) {
if (msg->addr & I2C_M_RD)
ls_i2c_handle_rx_addr(i2c_dev);
/* Clear ADDR flag */
readl(i2c_dev->base + I2C_SR2);
/* Enable buffer interrupts for RX/TX not empty events */
i2c_set_bits(i2c_dev->base + I2C_CR2, I2C_CR2_ITBUFEN);
}
if (msg->addr & I2C_M_RD) {
/* RX */
if (event & 0x40)
ls_i2c_handle_read(i2c_dev, 0);
if (event & 0x4)
ls_i2c_handle_read(i2c_dev, 1);
} else {
/* TX */
if (event & 0x84)
for (i = 0; i < 1 + !!((event & 0x84) == 0x84); i++)
ls_i2c_handle_write(i2c_dev);
}
return IRQ_HANDLED;
}
static int ls_i2c_xfer_msg(struct ls_i2c_dev *i2c_dev,
struct i2c_msg *msg, bool is_stop)
{
struct priv_msg *priv_msg = &i2c_dev->msg;
unsigned long timeout;
u32 status;
int ret;
priv_msg->addr = i2c_8bit_addr_from_msg(msg);
priv_msg->buf = msg->buf;
priv_msg->count = msg->len;
priv_msg->stop = is_stop;
priv_msg->result = 0;
reinit_completion(&i2c_dev->complete);
/* Enable events and errors interrupts */
i2c_set_bits(i2c_dev->base + I2C_CR2,
I2C_CR2_ITEVTEN | I2C_CR2_ITERREN);
timeout = wait_for_completion_timeout(&i2c_dev->complete,
i2c_dev->adap.timeout);
ret = priv_msg->result;
if (!timeout)
ret = -ETIMEDOUT;
ret = readl_poll_timeout(i2c_dev->base + reg,
status,
(!!(status & mask) == target),
20, 1000);
if (ret) {
dev_dbg(i2c_dev->dev, "wait timeout\n");
ret = -EBUSY;
}
return ret;
}
// i2c_wait_EV_signal 返回非 0 时所在对应函数返回 I2C_XFER_TIMEOUT_ERROR
#define i2c_wait_EV_signal_t(dev, reg_offset, mask, target) if (i2c_wait_EV_signal(dev, reg_offset, mask, target)) { return -EBUSY;}
/*
* @brief: i2c主模式,接收状态结束时的设置
* @param: base: i2c控制器基地址
* @param: stop: 是否发送关闭i2c总线信号
*/
static inline void i2c_setup_CR1_end_read(unsigned char *base, uint8_t stop)
{
unsigned int temp;
temp = readl((base + I2C_CR1));
temp |= (I2C_CR1_ACK | I2C_CR1_POS);
temp ^= (I2C_CR1_ACK | I2C_CR1_POS);
temp |= (stop << 9);
writel(temp, (base + I2C_CR1));
}
/*
* @brief: i2c主模式接收状态,读取i2c DR 寄存器,放到msg的data里面
* @param: base: i2c控制器基地址
* @param: msg: i2c读取描述(i2c_msg)实例指针
* @param: i: 当前读取数据所在data数组的下标
*/
static inline void i2c_update_read_msg_data(unsigned char *base, struct i2c_msg *msg, int i)
{
msg->buf[i] = ((readl(base + I2C_DR)) & 0xff);
}
/*
* @brief: i2c主模式接收状态,当只读取1个字节时的操作函数(从地址发送后的操作)
* @param: i2c_dev: ls_i2c_dev
* @param: msg: i2c读取描述(i2c_msg)实例指针
* @return: 0代表操作成功,否则操作失败
*/
static int i2c_xfer_r_1(struct ls_i2c_dev *i2c_dev, struct i2c_msg *msg, int is_stop)
{
unsigned char* base;
base = i2c_dev->base;
i2c_setup_CR1_end_read(base, is_stop);
i2c_wait_EV_signal_t(i2c_dev, I2C_SR1, I2C_SR1_RXNE, 1);
i2c_update_read_msg_data(base, msg, 0);
return 0;
}
/*
* @brief: i2c主模式接收状态,当只读取2个字节时的操作函数(从地址发送后的操作)
* @param: i2c_dev: ls_i2c_dev
* @param: msg: i2c读取描述(i2c_msg)实例指针
* @return: 0代表操作成功,否则操作失败
*/
static int i2c_xfer_r_2(struct ls_i2c_dev *i2c_dev, struct i2c_msg *msg, int is_stop)
{
unsigned char* base;
base = i2c_dev->base;
i2c_wait_EV_signal_t(i2c_dev, I2C_SR1, I2C_SR1_RXNE, 1);
i2c_update_read_msg_data(base, msg, 0);
i2c_setup_CR1_end_read(base, is_stop);
i2c_wait_EV_signal_t(i2c_dev, I2C_SR1, I2C_SR1_RXNE, 1);
i2c_update_read_msg_data(base, msg, 1);
return 0;
}
/*
* @brief: i2c主模式接收状态,当读取大于等于3个字节时的操作函数(从地址发送后的操作)
* @param: i2c_dev: ls_i2c_dev
* @param: msg: i2c读取描述(i2c_msg)实例指针
* @return: 0代表操作成功,否则操作失败
*/
static int i2c_xfer_r_3m(struct ls_i2c_dev *i2c_dev, struct i2c_msg *msg, int is_stop)
{
unsigned char* base;
int i;
int remain_read;
base = i2c_dev->base;
i = 0;
remain_read = msg->len;
while (1)
{
if (remain_read <= 3)
{
break;
}
// 倒数3个字节之前,看 I2C_SR1_RXNE 信号即可,有就读取DR
i2c_wait_EV_signal_t(i2c_dev, I2C_SR1, I2C_SR1_RXNE, 1);
i2c_update_read_msg_data(base, msg, i++);
--remain_read;
}
// 见2k300手册 主接收模式(非及时、3 字节)示意图
i2c_wait_EV_signal_t(i2c_dev, I2C_SR1, I2C_SR1_BTF, 1); // 倒数3个字节,I2C_SR1_BTF信号为1时,代表已经接收了两个字节
i2c_update_read_msg_data(base, msg, i++); // 读取DR,此时倒数第二个字节开始从移位寄存器到DR
i2c_setup_CR1_end_read(base, is_stop); // 下一个字节(也就是最后一个字节)之后需要发送 NACK 和 stop 命令了
i2c_wait_EV_signal_t(i2c_dev, I2C_SR1, I2C_SR1_BTF, 1); // 这时已经最后一个字节到来
i2c_update_read_msg_data(base, msg, i++); // 这次读取之后,等待移位寄存器填充DR
i2c_wait_EV_signal_t(i2c_dev, I2C_SR1, I2C_SR1_RXNE, 1); // 没有字节传输动作,但是移位寄存器已经把最后一个字节填充到DR
i2c_update_read_msg_data(base, msg, i++); // 读取DR
return 0;
}
/*
* @brief: i2c主模式读取数据处理函数
* @param: i2c_dev: ls_i2c_dev
* @param: msg: i2c读取描述(i2c_msg)实例指针
* @return: 0代表操作成功,否则操作失败
*/
static int i2c_xfer_r(struct ls_i2c_dev *i2c_dev, struct i2c_msg *msg, int is_stop)
{
unsigned char* base;
unsigned int temp;
unsigned char xfer_data;
int ret;
base = i2c_dev->base;
// START信号发送开始命令,ACK则会在接收到数据后发送ACK命令
temp = readl((base + I2C_CR1));
temp |= I2C_CR1_START;
temp |= I2C_CR1_ACK;
writel(temp, (base + I2C_CR1));
i2c_wait_EV_signal_t(i2c_dev, I2C_SR1, I2C_SR1_SB, 1);
// 把7bit地址左移一位,然后最后1bit设置为1,代表此从地址用于读取
xfer_data = msg->addr;
xfer_data <<= 1;
xfer_data |= 1; // bit 0 == 1 read
writeb(xfer_data, (base + I2C_DR));
i2c_wait_EV_signal_t(i2c_dev, I2C_SR1, I2C_SR1_ADDR, 1);
temp = readl((base + I2C_SR2));
// 针对不同的需要读取的字节数,调用不同的处理函数
if (msg->len == 1) // read 1 byte
{
ret = i2c_xfer_r_1(i2c_dev, msg, is_stop);
}
else if (msg->len == 2) // read 2 byte
{
ret = i2c_xfer_r_2(i2c_dev, msg, is_stop);
}
else if (msg->len > 3) // read 3 or more than 3 byte
{
ret = i2c_xfer_r_3m(i2c_dev, msg, is_stop);
}
if (ret)
return ret;
// 如果需要关闭总线,等待busy信号为0,代表总线总体已经空闲
if (is_stop)
{
i2c_wait_EV_signal_t(i2c_dev, I2C_SR2, I2C_SR2_BUSY, 0);
}
return 0;
}
/*
* @brief: i2c主模式写入数据处理函数
* @param: i2c_dev: ls_i2c_dev
* @param: msg: i2c写入描述(i2c_msg)实例指针
* @return: 0代表操作成功,否则操作失败
*/
static int i2c_xfer_w(struct ls_i2c_dev *i2c_dev, struct i2c_msg *msg, int is_stop)
{
unsigned char* base;
unsigned int temp;
int i;
unsigned char xfer_data;
base = i2c_dev->base;
// START信号发送开始命令,ACK则会在接收到数据后发送ACK命令
temp = readl((base + I2C_CR1));
temp |= I2C_CR1_START;
writel(temp, (base + I2C_CR1));
i2c_wait_EV_signal_t(i2c_dev, I2C_SR1, I2C_SR1_SB, 1);
// 把7bit地址左移一位,然后最后1bit设置为1,代表此从地址用于读取
xfer_data = msg->addr;
xfer_data <<= 1; // bit 0 == 0 write
writeb(xfer_data, (base + I2C_DR));
i2c_wait_EV_signal_t(i2c_dev, I2C_SR1, I2C_SR1_ADDR, 1);
temp = readl((base + I2C_SR2));
// 等待发送数据寄存器为空
i2c_wait_EV_signal_t(i2c_dev, I2C_SR1, I2C_SR1_TXE, 1);
i = 0;
while (1)
{
if (i == msg->len)
{
break;
}
xfer_data = msg->buf[i];
++i;
writeb(xfer_data, (base + I2C_DR));
// 等待传送结束
i2c_wait_EV_signal_t(i2c_dev, I2C_SR1, I2C_SR1_BTF, 1);
}
if (is_stop)
{
// 关闭总线
temp = readl((base + I2C_CR1));
temp |= (I2C_CR1_STOP);
writel(temp, (base + I2C_CR1));
// 等待busy信号为0,代表总线总体已经空闲
i2c_wait_EV_signal_t(i2c_dev, I2C_SR2, I2C_SR2_BUSY, 0);
}
return 0;
}
/**
* ls_i2c_xfer() - Transfer combined I2C message
* @i2c_adap: Adapter pointer to the controller
* @msgs: Pointer to data to be written.
* @num: Number of messages to be executed
*/
static int ls_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
int num)
static int ls_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
{
struct ls_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
int ret = 0;
struct i2c_msg* cur_msg;
int i;
int stop;
ret = ls_i2c_wait_free_bus(i2c_dev);
if (ret)
return ret;
/* START generation */
i2c_set_bits(i2c_dev->base + I2C_CR1, I2C_CR1_START);
for (i = 0; i < num && !ret; i++)
ret = ls_i2c_xfer_msg(i2c_dev, &msgs[i], i == num - 1);
for (i = 0; i < num; i++) {
cur_msg = msgs + i;
stop = (i == (num - 1));
if (cur_msg->flags & I2C_M_RD)
{
ret += i2c_xfer_r(i2c_dev, cur_msg, stop);
}
else
{
ret += i2c_xfer_w(i2c_dev, cur_msg, stop);
}
if (ret)
dev_err(i2c_dev->dev, "i2c %s error(%d)\r\n", (cur_msg->flags & I2C_M_RD) ? "read" : "write", ret);
}
return (ret < 0) ? ret : num;
}
@@ -445,15 +465,39 @@ static const struct i2c_algorithm ls_i2c_algo = {
.functionality = ls_i2c_func,
};
static void ls_i2c_bus_clock_probe(struct ls_i2c_dev *i2c_dev)
{
int ret;
struct clk* clk;
int of_clk_freq;
i2c_dev->freq = INPUT_DEFAULT_CLK;
ret = 1;
clk = devm_clk_get_optional_enabled(i2c_dev->dev, NULL);
if (clk) {
ret = devm_clk_rate_exclusive_get(i2c_dev->dev, clk);
if (!ret)
i2c_dev->freq = clk_get_rate(clk);
} else {
if (!of_property_read_u32(i2c_dev->dev->of_node, "clock-frequency", &of_clk_freq)) {
ret = 0;
i2c_dev->freq = of_clk_freq;
}
}
if (ret)
pr_info("%s warning: use default clk freq %d\n", __func__, INPUT_DEFAULT_CLK);
}
static int ls_i2c_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct ls_i2c_dev *i2c_dev;
struct resource *res;
u32 irq_event, clk_rate;
u32 clk_rate;
struct i2c_adapter *adap;
int ret;
int name_buffer_len;
int name_buffer_len;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -461,12 +505,6 @@ static int ls_i2c_probe(struct platform_device *pdev)
return -ENODEV;
}
irq_event = platform_get_irq(pdev, 0);
if (irq_event <= 0) {
dev_err(&pdev->dev, "IRQ event missing or invalid\n");
return -EINVAL;
}
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
if (!i2c_dev)
return -ENOMEM;
@@ -486,24 +524,18 @@ static int ls_i2c_probe(struct platform_device *pdev)
i2c_dev->dev = &pdev->dev;
ret = request_irq(irq_event, ls_i2c_isr_event, IRQF_SHARED,
pdev->name, i2c_dev);
if (ret) {
dev_err(&pdev->dev, "Failed to request irq event %i\n",
irq_event);
goto free_i2c_ioremap;
}
ls_i2c_bus_clock_probe(i2c_dev);
ls_i2c_hw_config(i2c_dev);
ls_i2c_disable_irq(i2c_dev); // 不需要中断 轮询等待
adap = &i2c_dev->adap;
i2c_set_adapdata(adap, i2c_dev);
adap->nr = pdev->id;
name_buffer_len = strlen(pdev->name);
name_buffer_len = (name_buffer_len >= sizeof(adap->name)) ? sizeof(adap->name) - 1 : name_buffer_len;
memset(adap->name, 0, name_buffer_len + 1);
name_buffer_len = strlen(pdev->name);
name_buffer_len = (name_buffer_len >= sizeof(adap->name)) ? sizeof(adap->name) - 1 : name_buffer_len;
memset(adap->name, 0, name_buffer_len + 1);
strncpy(adap->name, pdev->name, name_buffer_len);
adap->name[name_buffer_len] = 0;
adap->name[name_buffer_len] = 0;
adap->owner = THIS_MODULE;
adap->retries = 5;
adap->algo = &ls_i2c_algo;
+9 -1
View File
@@ -780,7 +780,15 @@ static void ls2k_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
host->status = "mmc request";
host->cmd_is_stop = 0;
host->mrq = mrq;
#if 1
// 部分 SD 卡会读取 EXT-REG 触发 CMD48(SD_READ_EXTR_SINGLE)
// 然而 LS2K300 CMD48 丢失中断,故直接不发送 CMD48 规避该问题
if (mrq->cmd->opcode == 48)
{
mmc_request_done(mmc, mrq);
return;
}
#endif
if (ls2k_mci_card_present(mmc) == 0) {
dbg(host, dbg_err, "%s: no medium present\n", __func__);
host->mrq->cmd->error = -ENOMEDIUM;
+8
View File
@@ -8,11 +8,19 @@
# matching values else you do not screw only LS CAN FD build but even
# base kernel build
ifeq ($(CONFIG_PREEMPT_RT), y)
quiet_cmd_build_lscanfd_dma = GEN $@
cmd_build_lscanfd_dma = cp $(obj)/lscanfd_dma.o_shipped_rt $@
quiet_cmd_build_lscanfd_platform = GEN $@
cmd_build_lscanfd_platform = cp $(obj)/lscanfd_platform.o_shipped_rt $@
else
quiet_cmd_build_lscanfd_dma = GEN $@
cmd_build_lscanfd_dma = cp $(obj)/lscanfd_dma.o_shipped $@
quiet_cmd_build_lscanfd_platform = GEN $@
cmd_build_lscanfd_platform = cp $(obj)/lscanfd_platform.o_shipped $@
endif
$(obj)/lscanfd_dma.o: FORCE
$(call if_changed,build_lscanfd_dma)
Binary file not shown.
Binary file not shown.
Binary file not shown.