mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2026-03-02 23:44:15 +01:00
qca: i2c: Enable i2c qup driver
These files are copied from: https://source.codeaurora.org/quic/qsdk/oss/boot/uboot-1.0/tree/drivers/i2c/ipq40xx_i2c.c https://source.codeaurora.org/quic/qsdk/oss/boot/uboot-1.0/tree/drivers/i2c/ipq40xx_i2c.h https://source.codeaurora.org/quic/qsdk/oss/boot/uboot-1.0/tree/arch/arm/cpu/armv7/qca/clock.c https://source.codeaurora.org/quic/qsdk/oss/boot/uboot-1.0/tree/arch/arm/include/asm/arch-qcom-common/clk.h Change-Id: If80f05b01ee168d2bfde454b9534f9a1db559b12 Signed-off-by: Ajay Kishore <akisho@codeaurora.org>
This commit is contained in:
parent
3891c01666
commit
39613cda7c
4 changed files with 1033 additions and 0 deletions
100
board/qca/common/clk.h
Normal file
100
board/qca/common/clk.h
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef QCA_CLK_H
|
||||
#define QCA_CLK_H
|
||||
|
||||
#define MMC_IDENTIFY_MODE 0
|
||||
#define MMC_DATA_TRANSFER_MODE 1
|
||||
|
||||
#define GCC_BLSP1_UART2_APPS_CFG_RCGR 0x01803038
|
||||
#define GCC_BLSP1_UART2_APPS_M 0x0180303C
|
||||
#define GCC_BLSP1_UART2_APPS_N 0x01803040
|
||||
#define GCC_BLSP1_UART2_APPS_D 0x01803044
|
||||
#define GCC_BLSP1_UART2_APPS_CMD_RCGR 0x01803034
|
||||
#define GCC_BLSP1_UART2_APPS_CBCR 0x0180302C
|
||||
|
||||
#define GCC_UART_CFG_RCGR_MODE_MASK 0x3000
|
||||
#define GCC_UART_CFG_RCGR_SRCSEL_MASK 0x0700
|
||||
#define GCC_UART_CFG_RCGR_SRCDIV_MASK 0x001F
|
||||
|
||||
#define GCC_UART_CFG_RCGR_MODE_SHIFT 12
|
||||
#define GCC_UART_CFG_RCGR_SRCSEL_SHIFT 8
|
||||
#define GCC_UART_CFG_RCGR_SRCDIV_SHIFT 0
|
||||
|
||||
#define UART2_RCGR_SRC_SEL 0x0
|
||||
#define UART2_RCGR_SRC_DIV 0x0
|
||||
#define UART2_RCGR_MODE 0x2
|
||||
#define UART2_CMD_RCGR_UPDATE 0x1
|
||||
#define UART2_CBCR_CLK_ENABLE 0x1
|
||||
|
||||
#define NOT_2D(two_d) (~two_d)
|
||||
#define NOT_N_MINUS_M(n,m) (~(n - m))
|
||||
#define CLOCK_UPDATE_TIMEOUT_US 1000
|
||||
|
||||
#ifdef CONFIG_IPQ40XX_I2C
|
||||
#define GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR 0x01802010
|
||||
|
||||
#define GCC_BLSP1_QUP1_I2C_APPS_M 0x0180303C
|
||||
#define GCC_BLSP1_QUP1_I2C_APPS_N 0x01803040
|
||||
#define GCC_BLSP1_QUP1_I2C_APPS_D 0x01803044
|
||||
#define GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR 0x0180200C
|
||||
#define GCC_BLSP1_QUP1_I2C_APPS_CBCR 0x01802008
|
||||
|
||||
#define GCC_I2C_CFG_RCGR_SRCSEL_MASK 0x0700
|
||||
#define GCC_I2C_CFG_RCGR_SRCDIV_MASK 0x001F
|
||||
|
||||
#define GCC_I2C_CFG_RCGR_SRCSEL_SHIFT 8
|
||||
#define GCC_I2C_CFG_RCGR_SRCDIV_SHIFT 0
|
||||
|
||||
#define I2C0_RCGR_SRC_SEL 1
|
||||
#define I2C0_RCGR_SRC_DIV 20
|
||||
#define I2C0_CMD_RCGR_UPDATE 0x1
|
||||
#define I2C0_CBCR_CLK_ENABLE 0x1
|
||||
#define NOT_2D(two_d) (~two_d)
|
||||
#define NOT_N_MINUS_M(n,m) (~(n - m))
|
||||
#define CLOCK_UPDATE_TIMEOUT_US 1000
|
||||
#endif
|
||||
|
||||
#define GCC_PCIE_SLEEP_CBCR 0x0181D014
|
||||
#define GCC_PCIE_AXI_M_CBCR 0x0181D004
|
||||
#define GCC_PCIE_AXI_S_CBCR 0x0181D008
|
||||
#define GCC_PCIE_AHB_CBCR 0x0181D00C
|
||||
#define PCIE_TIMEOUT_CNT 100
|
||||
#define ENABLE 0x1
|
||||
#define DISABLE 0x0
|
||||
#define BIT(s) (1<<s)
|
||||
|
||||
void emmc_clock_config(int mode);
|
||||
void emmc_clock_disable(void);
|
||||
|
||||
/* UART clocks configuration */
|
||||
void uart2_clock_config(unsigned int m,
|
||||
unsigned int n, unsigned int two_d);
|
||||
void uart2_toggle_clock(void);
|
||||
int uart2_trigger_update(void);
|
||||
void uart2_set_rate_mnd(unsigned int m,
|
||||
unsigned int n, unsigned int two_d);
|
||||
void uart2_configure_mux(void);
|
||||
|
||||
/* I2C clocks configuration */
|
||||
#ifdef CONFIG_IPQ40XX_I2C
|
||||
void i2c_clock_config(void);
|
||||
void i2c0_toggle_clock(void);
|
||||
int i2c0_trigger_update(void);
|
||||
void i2c0_configure_mux(void);
|
||||
#endif
|
||||
|
||||
int pcie_clock_enable(int clk_addr);
|
||||
void pcie_clock_disable(int clk_addr);
|
||||
#endif /*QCA_CLK_H*/
|
||||
207
board/qca/common/clock.c
Normal file
207
board/qca/common/clock.c
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch-qcom-common/clk.h>
|
||||
#include <asm/arch-ipq40xx/iomap.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
#define GCC_SDCC1_MISC 0x1818014
|
||||
#define GCC_SDCC1_APPS_CBCR 0x181800C
|
||||
#define GCC_SDCC1_APPS_RCGR 0x1818008
|
||||
#define GCC_SDCC1_APPS_CMD_RCGR 0x1818004
|
||||
|
||||
void emmc_clock_config(int mode)
|
||||
{
|
||||
/* Select SDCC clock source as DDR_PLL_SDCC1_CLK 192MHz */
|
||||
writel(0x100, GCC_SDCC1_APPS_RCGR);
|
||||
/* Update APPS_CMD_RCGR to reflect source selection */
|
||||
writel(0x1, GCC_SDCC1_APPS_CMD_RCGR);
|
||||
udelay(10);
|
||||
|
||||
if (mode == MMC_IDENTIFY_MODE) {
|
||||
/* Set root clock generator to bypass mode */
|
||||
writel(0x0, GCC_SDCC1_APPS_CBCR);
|
||||
udelay(10);
|
||||
/* Choose divider for 400KHz */
|
||||
writel(0x1e4 , GCC_SDCC1_MISC);
|
||||
/* Enable root clock generator */
|
||||
writel(0x1, GCC_SDCC1_APPS_CBCR);
|
||||
udelay(10);
|
||||
}
|
||||
if (mode == MMC_DATA_TRANSFER_MODE) {
|
||||
/* Set root clock generator to bypass mode */
|
||||
writel(0x0, GCC_SDCC1_APPS_CBCR);
|
||||
udelay(10);
|
||||
/* Choose divider for 48MHz */
|
||||
writel(0x3, GCC_SDCC1_MISC);
|
||||
/* Enable root clock generator */
|
||||
writel(0x1, GCC_SDCC1_APPS_CBCR);
|
||||
udelay(10);
|
||||
}
|
||||
}
|
||||
void emmc_clock_disable(void)
|
||||
{
|
||||
/* Clear divider */
|
||||
writel(0x0, GCC_SDCC1_MISC);
|
||||
|
||||
}
|
||||
|
||||
void uart2_configure_mux(void)
|
||||
{
|
||||
unsigned long cfg_rcgr;
|
||||
|
||||
cfg_rcgr = readl(GCC_BLSP1_UART2_APPS_CFG_RCGR);
|
||||
/* Clear mode, src sel, src div */
|
||||
cfg_rcgr &= ~(GCC_UART_CFG_RCGR_MODE_MASK |
|
||||
GCC_UART_CFG_RCGR_SRCSEL_MASK |
|
||||
GCC_UART_CFG_RCGR_SRCDIV_MASK);
|
||||
|
||||
cfg_rcgr |= ((UART2_RCGR_SRC_SEL << GCC_UART_CFG_RCGR_SRCSEL_SHIFT)
|
||||
& GCC_UART_CFG_RCGR_SRCSEL_MASK);
|
||||
|
||||
cfg_rcgr |= ((UART2_RCGR_SRC_DIV << GCC_UART_CFG_RCGR_SRCDIV_SHIFT)
|
||||
& GCC_UART_CFG_RCGR_SRCDIV_MASK);
|
||||
|
||||
cfg_rcgr |= ((UART2_RCGR_MODE << GCC_UART_CFG_RCGR_MODE_SHIFT)
|
||||
& GCC_UART_CFG_RCGR_MODE_MASK);
|
||||
|
||||
writel(cfg_rcgr, GCC_BLSP1_UART2_APPS_CFG_RCGR);
|
||||
}
|
||||
|
||||
void uart2_set_rate_mnd(unsigned int m,
|
||||
unsigned int n, unsigned int two_d)
|
||||
{
|
||||
writel(m, GCC_BLSP1_UART2_APPS_M);
|
||||
writel(NOT_N_MINUS_M(n, m), GCC_BLSP1_UART2_APPS_N);
|
||||
writel(NOT_2D(two_d), GCC_BLSP1_UART2_APPS_D);
|
||||
}
|
||||
|
||||
int uart2_trigger_update(void)
|
||||
{
|
||||
unsigned long cmd_rcgr;
|
||||
int timeout = 0;
|
||||
|
||||
cmd_rcgr = readl(GCC_BLSP1_UART2_APPS_CMD_RCGR);
|
||||
cmd_rcgr |= UART2_CMD_RCGR_UPDATE;
|
||||
writel(cmd_rcgr, GCC_BLSP1_UART2_APPS_CMD_RCGR);
|
||||
|
||||
while (readl(GCC_BLSP1_UART2_APPS_CMD_RCGR) & UART2_CMD_RCGR_UPDATE) {
|
||||
if (timeout++ >= CLOCK_UPDATE_TIMEOUT_US) {
|
||||
printf("Timeout waiting for UART2 clock update\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
udelay(1);
|
||||
}
|
||||
cmd_rcgr = readl(GCC_BLSP1_UART2_APPS_CMD_RCGR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uart2_toggle_clock(void)
|
||||
{
|
||||
unsigned long cbcr_val;
|
||||
|
||||
cbcr_val = readl(GCC_BLSP1_UART2_APPS_CBCR);
|
||||
cbcr_val |= UART2_CBCR_CLK_ENABLE;
|
||||
writel(cbcr_val, GCC_BLSP1_UART2_APPS_CBCR);
|
||||
}
|
||||
|
||||
void uart2_clock_config(unsigned int m,
|
||||
unsigned int n, unsigned int two_d)
|
||||
{
|
||||
uart2_configure_mux();
|
||||
uart2_set_rate_mnd(m, n, two_d);
|
||||
uart2_trigger_update();
|
||||
uart2_toggle_clock();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPQ40XX_I2C
|
||||
void i2c0_configure_mux(void)
|
||||
{
|
||||
unsigned long cfg_rcgr;
|
||||
|
||||
cfg_rcgr = readl(GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR);
|
||||
/* Clear mode, src sel, src div */
|
||||
cfg_rcgr &= ~(GCC_I2C_CFG_RCGR_SRCSEL_MASK |
|
||||
GCC_I2C_CFG_RCGR_SRCDIV_MASK);
|
||||
|
||||
cfg_rcgr |= ((I2C0_RCGR_SRC_SEL << GCC_I2C_CFG_RCGR_SRCSEL_SHIFT)
|
||||
& GCC_UART_CFG_RCGR_SRCSEL_MASK);
|
||||
|
||||
cfg_rcgr |= ((I2C0_RCGR_SRC_DIV << GCC_I2C_CFG_RCGR_SRCDIV_SHIFT)
|
||||
& GCC_UART_CFG_RCGR_SRCDIV_MASK);
|
||||
|
||||
writel(cfg_rcgr, GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR);
|
||||
}
|
||||
|
||||
int i2c0_trigger_update(void)
|
||||
{
|
||||
unsigned long cmd_rcgr;
|
||||
int timeout = 0;
|
||||
|
||||
cmd_rcgr = readl(GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR);
|
||||
cmd_rcgr |= I2C0_CMD_RCGR_UPDATE;
|
||||
writel(cmd_rcgr, GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR);
|
||||
|
||||
while (readl(GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR) & I2C0_CMD_RCGR_UPDATE) {
|
||||
if (timeout++ >= CLOCK_UPDATE_TIMEOUT_US) {
|
||||
printf("Timeout waiting for I2C0 clock update\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
udelay(1);
|
||||
}
|
||||
cmd_rcgr = readl(GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2c0_toggle_clock(void)
|
||||
{
|
||||
unsigned long cbcr_val;
|
||||
|
||||
cbcr_val = readl(GCC_BLSP1_QUP1_I2C_APPS_CBCR);
|
||||
cbcr_val |= I2C0_CBCR_CLK_ENABLE;
|
||||
writel(cbcr_val, GCC_BLSP1_QUP1_I2C_APPS_CBCR);
|
||||
}
|
||||
|
||||
void i2c_clock_config(void)
|
||||
{
|
||||
i2c0_configure_mux();
|
||||
i2c0_trigger_update();
|
||||
i2c0_toggle_clock();
|
||||
}
|
||||
#endif
|
||||
|
||||
int pcie_clock_enable(int clk_addr)
|
||||
{
|
||||
unsigned int count = PCIE_TIMEOUT_CNT;
|
||||
int state, val;
|
||||
|
||||
writel(ENABLE, clk_addr);
|
||||
do {
|
||||
val = readl(clk_addr);
|
||||
count--;
|
||||
if (count == 0) {
|
||||
printf("Timeout waiting for %d enable \n", clk_addr);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
state = (val & BIT(31));
|
||||
udelay(10);
|
||||
} while (state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pcie_clock_disable(int clk_addr)
|
||||
{
|
||||
writel(0, clk_addr);
|
||||
}
|
||||
605
drivers/i2c/qup_i2c.c
Normal file
605
drivers/i2c/qup_i2c.c
Normal file
|
|
@ -0,0 +1,605 @@
|
|||
/*
|
||||
* Copyright (c) 2015 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include "ipq40xx_i2c.h"
|
||||
#include <asm/io.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/arch-qcom-common/clk.h>
|
||||
#include "ipq40xx_cdp.h"
|
||||
|
||||
static int i2c_base_addr;
|
||||
static int i2c_hw_initialized;
|
||||
static int i2c_board_initialized;
|
||||
|
||||
/*
|
||||
* Reset entire QUP and all mini cores
|
||||
*/
|
||||
static void i2c_reset(void)
|
||||
{
|
||||
writel(0x1, (i2c_base_addr + QUP_SW_RESET_OFFSET));
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
static int check_bit_state(uint32_t reg_addr, int bit_num, int val,
|
||||
int us_delay)
|
||||
{
|
||||
unsigned int count = TIMEOUT_CNT;
|
||||
unsigned int bit_val = ((readl(reg_addr) >> bit_num) & 0x01);
|
||||
|
||||
while (bit_val != val) {
|
||||
count--;
|
||||
if (count == 0) {
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
udelay(us_delay);
|
||||
bit_val = ((readl(reg_addr) >> bit_num) & 0x01);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether QUP State is valid
|
||||
*/
|
||||
static int check_qup_state_valid(void)
|
||||
{
|
||||
return check_bit_state(i2c_base_addr + QUP_STATE_OFFSET,
|
||||
QUP_STATE_VALID_BIT,
|
||||
QUP_STATE_VALID, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure QUP Core state
|
||||
*/
|
||||
static int config_i2c_state(unsigned int state)
|
||||
{
|
||||
uint32_t val;
|
||||
int ret = SUCCESS;
|
||||
|
||||
ret = check_qup_state_valid();
|
||||
if (ret != SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* Set the state */
|
||||
val = readl(i2c_base_addr + QUP_STATE_OFFSET);
|
||||
val = ((val & ~QUP_STATE_MASK) | state);
|
||||
writel(val, (i2c_base_addr + QUP_STATE_OFFSET));
|
||||
ret = check_qup_state_valid();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure I2C IO Mode.
|
||||
*/
|
||||
void config_i2c_mode(void)
|
||||
{
|
||||
int cfg;
|
||||
|
||||
cfg = readl(i2c_base_addr + QUP_IO_MODES_OFFSET);
|
||||
cfg |= (INPUT_FIFO_MODE | OUTPUT_FIFO_MODE | PACK_EN | UNPACK_EN);
|
||||
writel(cfg, i2c_base_addr + QUP_IO_MODES_OFFSET);
|
||||
}
|
||||
|
||||
void i2c_qca_board_init(void)
|
||||
{
|
||||
i2c_base_addr = gboard_param->i2c_cfg->i2c_base;
|
||||
qca_configure_gpio(gboard_param->i2c_cfg->i2c_gpio, NO_OF_I2C_GPIOS);
|
||||
|
||||
/* Configure the I2C clock */
|
||||
i2c_clock_config();
|
||||
|
||||
i2c_hw_initialized = 0;
|
||||
i2c_board_initialized = 1;
|
||||
}
|
||||
|
||||
void i2c_qup_mini_core_init(void)
|
||||
{
|
||||
int cfg;
|
||||
|
||||
cfg = readl(i2c_base_addr + QUP_CONFIG_OFFSET);
|
||||
cfg |= (QUP_CONFIG_MINI_CORE_I2C) | (I2C_BIT_WORD);
|
||||
|
||||
writel(cfg, i2c_base_addr + QUP_CONFIG_OFFSET);
|
||||
|
||||
writel(QUP_EN_VERSION_TWO_TAG, (i2c_base_addr +
|
||||
QUP_I2C_MASTER_CONFIG_OFFSET));
|
||||
}
|
||||
|
||||
/*
|
||||
* QUP I2C Hardware Initialisation
|
||||
*/
|
||||
static int i2c_hw_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* QUP configuration */
|
||||
i2c_reset();
|
||||
|
||||
/* Set the BLSP QUP state */
|
||||
ret = check_qup_state_valid();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
writel(0,(i2c_base_addr + QUP_CONFIG_OFFSET));
|
||||
|
||||
writel(QUP_APP_CLK_ON_EN | QUP_CORE_CLK_ON_EN |
|
||||
QUP_FIFO_CLK_GATE_EN, (i2c_base_addr + QUP_CONFIG_OFFSET));
|
||||
|
||||
writel(0, i2c_base_addr + QUP_I2C_MASTER_CLK_CTL_OFFSET);
|
||||
writel(0, i2c_base_addr + QUP_TEST_CTRL_OFFSET);
|
||||
writel(0, i2c_base_addr + QUP_IO_MODES_OFFSET);
|
||||
writel(0, i2c_base_addr + QUP_OPERATIONAL_MASK_OFFSET);
|
||||
|
||||
i2c_qup_mini_core_init();
|
||||
|
||||
config_i2c_mode();
|
||||
|
||||
writel(QUP_MX_READ_COUNT, i2c_base_addr + QUP_MX_READ_COUNT_OFFSET);
|
||||
writel(QUP_MX_WRITE_COUNT, i2c_base_addr + QUP_MX_WRITE_COUNT_OFFSET);
|
||||
|
||||
|
||||
writel(QUP_MX_INPUT_COUNT, i2c_base_addr + QUP_MX_INPUT_COUNT_OFFSET);
|
||||
writel(QUP_MX_OUTPUT_COUNT, i2c_base_addr + QUP_MX_OUTPUT_COUNT_OFFSET);
|
||||
|
||||
ret = config_i2c_state(QUP_STATE_RESET);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
i2c_hw_initialized = 1;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to check wheather Input or Output FIFO
|
||||
* has data to be serviced. For invalid slaves, this
|
||||
* flag will not be set.
|
||||
*/
|
||||
static int check_fifo_status(uint dir)
|
||||
{
|
||||
unsigned int count = TIMEOUT_CNT;
|
||||
unsigned int status_flag;
|
||||
unsigned int val;
|
||||
|
||||
if (dir == READ) {
|
||||
do {
|
||||
val = readl(i2c_base_addr
|
||||
+ QUP_OPERATIONAL_OFFSET);
|
||||
count--;
|
||||
if (count == 0)
|
||||
return -ETIMEDOUT;
|
||||
status_flag = val & INPUT_SERVICE_FLAG;
|
||||
udelay(10);
|
||||
} while (!status_flag);
|
||||
|
||||
} else if (dir == WRITE) {
|
||||
do {
|
||||
val = readl(i2c_base_addr
|
||||
+ QUP_OPERATIONAL_OFFSET);
|
||||
count--;
|
||||
if (count == 0)
|
||||
return -ETIMEDOUT;
|
||||
status_flag = val & OUTPUT_FIFO_FULL;
|
||||
udelay(10);
|
||||
} while (status_flag);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the values in the OUTPUT FIFO are shifted out.
|
||||
*/
|
||||
static int check_write_done(void)
|
||||
{
|
||||
unsigned int count = TIMEOUT_CNT;
|
||||
unsigned int status_flag;
|
||||
unsigned int val;
|
||||
|
||||
do {
|
||||
val = readl(i2c_base_addr
|
||||
+ QUP_OPERATIONAL_OFFSET);
|
||||
count--;
|
||||
if (count == 0)
|
||||
return -ETIMEDOUT;
|
||||
status_flag = val & OUTPUT_FIFO_NOT_EMPTY;
|
||||
udelay(10);
|
||||
} while (status_flag);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int i2c_process_read_data(uint32_t data, uchar *buffer, int len)
|
||||
{
|
||||
int idx = 0;
|
||||
uint8_t data_8 = 0;
|
||||
int index = 0;
|
||||
int rd_len = len;
|
||||
|
||||
while (index < 4 && rd_len) {
|
||||
data_8 = QUP_I2C_DATA(data);
|
||||
index++;
|
||||
if (data_8 == QUP_I2C_DATA_READ_AND_STOP_SEQ) {
|
||||
index++;
|
||||
data = (data >> 16);
|
||||
continue;
|
||||
}
|
||||
if (data_8 == QUP_I2C_STOP_SEQ)
|
||||
break;
|
||||
if (data_8 == QUP_I2C_NOP_PADDING) {
|
||||
data = (data >> 8);
|
||||
continue;
|
||||
}
|
||||
buffer[idx] = data_8;
|
||||
rd_len--;
|
||||
idx++;
|
||||
data = (data >> 8);
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
uint32_t i2c_write_read_offset(uchar chip, int alen)
|
||||
{
|
||||
uint32_t tag;
|
||||
uint32_t *fifo;
|
||||
|
||||
fifo = (uint32_t *) (i2c_base_addr + QUP_OUTPUT_FIFO_OFFSET);
|
||||
tag = QUP_I2C_START_SEQ;
|
||||
tag |= ((QUP_I2C_ADDR(chip)) | (I2C_WRITE)) << 8;
|
||||
tag |= QUP_I2C_DATA_WRITE_SEQ << 16;
|
||||
tag |= alen << 24;
|
||||
writel(tag, fifo);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
uint32_t i2c_write_read_tag(uchar chip, uint addr, int alen, int data_len)
|
||||
{
|
||||
uint32_t tag = 0;
|
||||
uint32_t *fifo;
|
||||
|
||||
fifo = (uint32_t *) (i2c_base_addr + QUP_OUTPUT_FIFO_OFFSET);
|
||||
|
||||
if (alen == 2) {
|
||||
/* based on the slave send msb 8 bits or lsb 8 bits first */
|
||||
tag = QUP_I2C_DATA(addr);
|
||||
tag |= QUP_I2C_DATA(addr >> 8) << 8;
|
||||
tag |= QUP_I2C_START_SEQ << 16;
|
||||
tag |= ((QUP_I2C_ADDR(chip)) | (I2C_READ)) << 24;
|
||||
writel(tag, fifo);
|
||||
|
||||
tag = 0;
|
||||
tag |= QUP_I2C_DATA_READ_AND_STOP_SEQ;
|
||||
tag |= data_len << 8;
|
||||
writel(tag, fifo);
|
||||
} else if (alen == 1) {
|
||||
tag = QUP_I2C_DATA(addr);
|
||||
tag |= QUP_I2C_START_SEQ << 8;
|
||||
tag |= ((QUP_I2C_ADDR(chip)) | (I2C_READ)) << 16;
|
||||
tag |= (QUP_I2C_DATA_READ_AND_STOP_SEQ << 24);
|
||||
writel(tag, fifo);
|
||||
|
||||
tag = 0;
|
||||
tag |= data_len;
|
||||
writel(tag, fifo);
|
||||
} else if (alen == 0) {
|
||||
tag |= QUP_I2C_START_SEQ;
|
||||
tag |= ((QUP_I2C_ADDR(chip)) | (I2C_READ)) << 8;
|
||||
tag |= (QUP_I2C_DATA_READ_AND_STOP_SEQ << 16);
|
||||
tag |= data_len << 24;
|
||||
writel(tag, fifo);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
|
||||
{
|
||||
int ret = 0;
|
||||
int nack = 0;
|
||||
uint32_t data = 0;
|
||||
uint8_t data_len = len;
|
||||
uint32_t *fifo;
|
||||
int idx = 0;
|
||||
int cfg;
|
||||
|
||||
i2c_base_addr = gboard_param->i2c_cfg->i2c_base;
|
||||
|
||||
config_i2c_state(QUP_STATE_RESET);
|
||||
|
||||
if (!i2c_board_initialized) {
|
||||
i2c_qca_board_init();
|
||||
}
|
||||
|
||||
if (!i2c_hw_initialized) {
|
||||
i2c_hw_init();
|
||||
}
|
||||
|
||||
writel(0x3C, i2c_base_addr + QUP_ERROR_FLAGS_OFFSET);
|
||||
writel(0x3C, i2c_base_addr + QUP_ERROR_FLAGS_EN_OFFSET);
|
||||
writel(0, i2c_base_addr + QUP_I2C_MASTER_STATUS_OFFSET);
|
||||
|
||||
if (alen != 0)
|
||||
writel((OUT_FIFO_RD_TAG_BYTE_CNT + alen),
|
||||
i2c_base_addr + QUP_MX_WRITE_COUNT_OFFSET);
|
||||
else
|
||||
writel(OUT_FIFO_WR_TAG_BYTE_CNT,
|
||||
i2c_base_addr + QUP_MX_WRITE_COUNT_OFFSET);
|
||||
|
||||
writel((IN_FIFO_TAG_BYTE_CNT + data_len),
|
||||
i2c_base_addr + QUP_MX_READ_COUNT_OFFSET);
|
||||
|
||||
/* Set to RUN state */
|
||||
ret = config_i2c_state(QUP_STATE_RUN);
|
||||
if (ret != SUCCESS) {
|
||||
debug("State run failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Configure the I2C Master clock */
|
||||
cfg = (QUP_INPUT_CLK / (I2C_CLK_100KHZ * 2)) - 3;
|
||||
writel(cfg, i2c_base_addr + QUP_I2C_MASTER_CLK_CTL_OFFSET);
|
||||
/* Write to FIFO in Pause State */
|
||||
/* Set to PAUSE state */
|
||||
ret = config_i2c_state(QUP_STATE_PAUSE);
|
||||
if (ret != SUCCESS) {
|
||||
debug("State Pause failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
fifo = (uint32_t *) (i2c_base_addr + QUP_OUTPUT_FIFO_OFFSET);
|
||||
|
||||
if (alen != 0)
|
||||
data = i2c_write_read_offset(chip, alen);
|
||||
|
||||
data = i2c_write_read_tag(chip, addr, alen, data_len);
|
||||
|
||||
/* Set to RUN state */
|
||||
ret = config_i2c_state(QUP_STATE_RUN);
|
||||
if (ret != SUCCESS) {
|
||||
debug("State run failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
mdelay(2);
|
||||
ret = check_write_done();
|
||||
if (ret != SUCCESS) {
|
||||
debug("Write done failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
nack = readl(i2c_base_addr + QUP_I2C_MASTER_STATUS_OFFSET) & NACK_BIT_MASK;
|
||||
nack = nack >> NACK_BIT_SHIFT;
|
||||
if (nack == 1) {
|
||||
debug("NACK RECVD\n");
|
||||
return -ENACK;
|
||||
}
|
||||
|
||||
if (readl(i2c_base_addr + QUP_OPERATIONAL_OFFSET)
|
||||
& OUTPUT_SERVICE_FLAG) {
|
||||
writel(OUTPUT_SERVICE_FLAG,
|
||||
i2c_base_addr + QUP_OPERATIONAL_OFFSET);
|
||||
}
|
||||
|
||||
fifo = (uint32_t *)(i2c_base_addr + QUP_INPUT_FIFO_OFFSET);
|
||||
|
||||
mdelay(2);
|
||||
ret = check_fifo_status(READ);
|
||||
if (ret != SUCCESS) {
|
||||
debug("Read status failed\n");
|
||||
goto out;
|
||||
}
|
||||
while (len) {
|
||||
/* Read the data from the FIFO */
|
||||
data = readl(fifo);
|
||||
|
||||
ret = i2c_process_read_data(data, buffer + idx, len);
|
||||
if (ret) {
|
||||
idx += ret;
|
||||
len -= ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (readl(i2c_base_addr + QUP_OPERATIONAL_OFFSET)
|
||||
& INPUT_SERVICE_FLAG) {
|
||||
writel(INPUT_SERVICE_FLAG,
|
||||
i2c_base_addr + QUP_OPERATIONAL_OFFSET);
|
||||
}
|
||||
(void)config_i2c_state(QUP_STATE_RESET);
|
||||
return SUCCESS;
|
||||
out:
|
||||
/*
|
||||
* Put the I2C Core back in the Reset State to end the transfer.
|
||||
*/
|
||||
(void)config_i2c_state(QUP_STATE_RESET);
|
||||
writel(QUP_MX_READ_COUNT, i2c_base_addr + QUP_MX_READ_COUNT_OFFSET);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int create_data_byte(uint16_t *data, uchar *buffer, int len)
|
||||
{
|
||||
int idx = 0;
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
*data = QUP_I2C_DATA(buffer[idx]);
|
||||
idx++;
|
||||
len--;
|
||||
}
|
||||
if (len == 0) {
|
||||
return idx;
|
||||
} else {
|
||||
*data = (*data << 8);
|
||||
*data |= QUP_I2C_DATA(buffer[idx]);
|
||||
idx++;
|
||||
len--;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
uint32_t i2c_frame_wr_tag(uchar chip, uint8_t data_len, int alen)
|
||||
{
|
||||
uint32_t tag;
|
||||
|
||||
tag = QUP_I2C_START_SEQ;
|
||||
tag |= (((QUP_I2C_ADDR(chip)) | (I2C_WRITE)) << 8);
|
||||
tag |= (QUP_I2C_DATA_WRITE_AND_STOP_SEQ << 16);
|
||||
tag |= (data_len + alen) << 24;
|
||||
return tag;
|
||||
}
|
||||
|
||||
int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
|
||||
{
|
||||
int ret = 0;
|
||||
int nack = 0;
|
||||
int idx = 0;
|
||||
int first = 1;
|
||||
uint32_t data = 0;
|
||||
uint16_t data_lsb_16 = 0;
|
||||
uint16_t data_msb_16 = 0;
|
||||
uint8_t data_len = len;
|
||||
uint32_t *fifo;
|
||||
uint32_t cfg;
|
||||
|
||||
i2c_base_addr = gboard_param->i2c_cfg->i2c_base;
|
||||
|
||||
/* Set to Reset State */
|
||||
ret = config_i2c_state(QUP_STATE_RESET);
|
||||
|
||||
if (!i2c_board_initialized) {
|
||||
i2c_qca_board_init();
|
||||
}
|
||||
|
||||
if (!i2c_hw_initialized) {
|
||||
i2c_hw_init();
|
||||
}
|
||||
|
||||
writel(0x3C, i2c_base_addr + QUP_ERROR_FLAGS_OFFSET);
|
||||
writel(0x3C, i2c_base_addr + QUP_ERROR_FLAGS_EN_OFFSET);
|
||||
writel(0, i2c_base_addr + QUP_I2C_MASTER_STATUS_OFFSET);
|
||||
|
||||
writel((OUT_FIFO_WR_TAG_BYTE_CNT + len + alen),
|
||||
i2c_base_addr + QUP_MX_WRITE_COUNT_OFFSET);
|
||||
|
||||
|
||||
/* Set to RUN state */
|
||||
ret = config_i2c_state(QUP_STATE_RUN);
|
||||
if (ret != SUCCESS) {
|
||||
debug("State run failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Configure the I2C Master clock */
|
||||
cfg = (QUP_INPUT_CLK / (I2C_CLK_100KHZ * 2)) - 3;
|
||||
writel(cfg, i2c_base_addr + QUP_I2C_MASTER_CLK_CTL_OFFSET);
|
||||
|
||||
|
||||
/* Write to FIFO in Pause State */
|
||||
/* Set to PAUSE state */
|
||||
ret = config_i2c_state(QUP_STATE_PAUSE);
|
||||
if (ret != SUCCESS) {
|
||||
debug("State Pause failed\n");
|
||||
goto out;
|
||||
}
|
||||
fifo = (uint32_t *) (i2c_base_addr + QUP_OUTPUT_FIFO_OFFSET);
|
||||
data = i2c_frame_wr_tag(chip, data_len, alen);
|
||||
|
||||
/* Write tags to the FIFO along with Slave address
|
||||
* and Write len */
|
||||
writel(data, fifo);
|
||||
|
||||
while (len > 0) {
|
||||
data_lsb_16 = 0;
|
||||
data_msb_16 = 0;
|
||||
data = 0;
|
||||
if ((first == 1) && (alen != 0)) {
|
||||
if (alen == 2) {
|
||||
/* based on the slave send msb 8 bits or lsb 8 bits first */
|
||||
data_lsb_16 = QUP_I2C_DATA(addr);
|
||||
data_lsb_16 |= QUP_I2C_DATA(addr >> 8) << 8;
|
||||
} else if (alen == 1) {
|
||||
data_lsb_16 = QUP_I2C_DATA(addr);
|
||||
data_lsb_16 |= QUP_I2C_DATA(buffer[idx]) << 8;
|
||||
idx++;
|
||||
len --;
|
||||
}
|
||||
first = 0;
|
||||
ret = 2;
|
||||
} else {
|
||||
ret = create_data_byte(&data_lsb_16, buffer + idx, len);
|
||||
idx += ret;
|
||||
len -= ret;
|
||||
}
|
||||
if(ret == 2) {
|
||||
ret = create_data_byte(&data_msb_16, buffer + idx, len);
|
||||
idx += ret;
|
||||
len -= ret;
|
||||
}
|
||||
data |= data_msb_16;
|
||||
data = (data << 16);
|
||||
data |= data_lsb_16;
|
||||
writel(data, fifo);
|
||||
}
|
||||
|
||||
/* Set to RUN state */
|
||||
ret = config_i2c_state(QUP_STATE_RUN);
|
||||
if (ret != SUCCESS) {
|
||||
debug("State Run failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Clear Operational Flag */
|
||||
if (readl(i2c_base_addr + QUP_OPERATIONAL_OFFSET)
|
||||
& OUTPUT_SERVICE_FLAG) {
|
||||
writel(OUTPUT_SERVICE_FLAG,
|
||||
i2c_base_addr + QUP_OPERATIONAL_OFFSET);
|
||||
}
|
||||
|
||||
mdelay(2);
|
||||
ret = check_write_done();
|
||||
if (ret != SUCCESS) {
|
||||
debug("Write done failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
nack = readl(i2c_base_addr + QUP_I2C_MASTER_STATUS_OFFSET) & NACK_BIT_MASK;
|
||||
nack = nack >> NACK_BIT_SHIFT;
|
||||
if (nack == 1) {
|
||||
debug("NACK RECVD\n");
|
||||
return -ENACK;
|
||||
}
|
||||
out:
|
||||
/*
|
||||
* Put the I2C Core back in the Reset State to end the transfer.
|
||||
*/
|
||||
(void)config_i2c_state(QUP_STATE_RESET);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Probe the given I2C chip address.
|
||||
* Returns 0 if a chip responded.
|
||||
*/
|
||||
int i2c_probe(uchar chip)
|
||||
{
|
||||
uchar buf;
|
||||
|
||||
/*send the third parameter alen as per the i2c slave*/
|
||||
return i2c_read(chip, 0x0, 0x0, &buf, 0x1);
|
||||
}
|
||||
|
||||
void i2c_init(int speed, int slaveaddr)
|
||||
{
|
||||
debug("i2c_init(speed=%u, slaveaddr=0x%x)\n", speed, slaveaddr);
|
||||
}
|
||||
121
drivers/i2c/qup_i2c.h
Normal file
121
drivers/i2c/qup_i2c.h
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2015 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#define I2C_STATUS_ERROR_MASK 0x38000FC
|
||||
|
||||
/* QUP Core register offsets */
|
||||
#define QUP_CONFIG_OFFSET 0x0
|
||||
#define QUP_STATE_OFFSET 0x4
|
||||
#define QUP_IO_MODES_OFFSET 0x8
|
||||
#define QUP_SW_RESET_OFFSET 0xc
|
||||
#define QUP_TIME_OUT_OFFSET 0x10
|
||||
#define QUP_TIME_OUT_CURRENT_OFFSET 0x14
|
||||
#define QUP_OPERATIONAL_OFFSET 0x18
|
||||
#define QUP_ERROR_FLAGS_OFFSET 0x1c
|
||||
#define QUP_ERROR_FLAGS_EN_OFFSET 0x20
|
||||
#define QUP_TEST_CTRL_OFFSET 0x24
|
||||
#define QUP_OPERATIONAL_MASK_OFFSET 0x28
|
||||
#define QUP_MX_OUTPUT_COUNT_OFFSET 0x100
|
||||
#define QUP_MX_OUTPUT_CNT_CURRENT_OFFSET 0x104
|
||||
#define QUP_OUTPUT_DEBUG_OFFSET 0x108
|
||||
#define QUP_OUTPUT_FIFO_WORD_CNT_OFFSET 0x10c
|
||||
#define QUP_OUTPUT_FIFO_OFFSET 0x110
|
||||
#define QUP_MX_WRITE_COUNT_OFFSET 0x150
|
||||
#define QUP_WRITE_CNT_CURRENT_OFFSET 0x154
|
||||
#define QUP_MX_INPUT_COUNT_OFFSET 0x200
|
||||
#define QUP_MX_READ_COUNT_OFFSET 0x208
|
||||
#define QUP_MX_READ_CNT_CURRENT_OFFSET 0x20c
|
||||
#define QUP_INPUT_DEBUG_OFFSET 0x210
|
||||
#define QUP_INPUT_FIFO_WORD_CNT_OFFSET 0x214
|
||||
#define QUP_INPUT_FIFO_OFFSET 0x218
|
||||
#define QUP_I2C_MASTER_CLK_CTL_OFFSET 0x400
|
||||
#define QUP_I2C_MASTER_STATUS_OFFSET 0x404
|
||||
#define QUP_I2C_MASTER_CONFIG_OFFSET 0x408
|
||||
#define QUP_MAX_OFFSET 0xfff
|
||||
|
||||
#define QUP_MX_OUTPUT_COUNT 0x0000
|
||||
#define QUP_MX_INPUT_COUNT 0x0000
|
||||
#define QUP_MX_WRITE_COUNT 0x0000
|
||||
#define QUP_MX_READ_COUNT 0x0000
|
||||
|
||||
#define SUCCESS 0
|
||||
#define ENACK 1
|
||||
#define TIMEOUT_CNT 100
|
||||
|
||||
#define QUP_STATE_RESET 0x0
|
||||
#define QUP_STATE_RUN 0x1D
|
||||
#define QUP_STATE_PAUSE 0x1F
|
||||
#define QUP_STATE_VALID_BIT 2
|
||||
#define QUP_STATE_VALID 1
|
||||
#define QUP_STATE_MASK 0x3
|
||||
|
||||
#define NACK_BIT_MASK 0x8
|
||||
#define NACK_BIT_SHIFT 3
|
||||
|
||||
#define QUP_CONFIG_MINI_CORE_I2C (2 << 8)
|
||||
#define I2C_BIT_WORD 0x7
|
||||
#define INPUT_FIFO_MODE (0x0 << 12)
|
||||
#define OUTPUT_FIFO_MODE (0x0 << 10)
|
||||
#define INPUT_BLOCK_MODE (0x01 << 12)
|
||||
#define OUTPUT_BLOCK_MODE (0x01 << 10)
|
||||
#define PACK_EN (0x01 << 15)
|
||||
#define UNPACK_EN (0x01 << 14)
|
||||
#define OUTPUT_BIT_SHIFT_EN (0x01 << 16)
|
||||
#define ERROR_FLAGS_EN 0x3C
|
||||
#define I2C_MASTER_STATUS_CLEAR 0xFFFFFC
|
||||
#define QUP_DATA_AVAILABLE_FOR_READ (1 << 5)
|
||||
#define OUTPUT_SERVICE_FLAG (1 << 8)
|
||||
#define INPUT_SERVICE_FLAG (1 << 9)
|
||||
#define MAX_OUTPUT_DONE_FLAG (1 << 10)
|
||||
#define MAX_INPUT_DONE_FLAG (1 << 11)
|
||||
#define OUTPUT_FIFO_NOT_EMPTY (1 << 4)
|
||||
#define OUTPUT_FIFO_FULL (1 << 6)
|
||||
#define INPUT_FIFO_NOT_EMPTY (1 << 5)
|
||||
#define INPUT_FIFO_FULL (1 << 7)
|
||||
#define QUP_APP_CLK_ON_EN (1 << 12)
|
||||
#define QUP_CORE_CLK_ON_EN (1 << 13)
|
||||
#define QUP_FIFO_CLK_GATE_EN (1 << 14)
|
||||
#define QUP_EN_VERSION_TWO_TAG 1
|
||||
|
||||
#define I2C_WRITE 0x0
|
||||
#define I2C_READ 0x1
|
||||
#define QUP_I2C_START_SEQ 0x81
|
||||
#define QUP_I2C_DATA_WRITE_SEQ 0x82
|
||||
#define QUP_I2C_DATA_WRITE_AND_STOP_SEQ 0x83
|
||||
#define QUP_I2C_DATA_READ_SEQ 0x85
|
||||
#define QUP_I2C_DATA_READ_AND_STOP_SEQ 0x87
|
||||
#define QUP_I2C_STOP_SEQ 0x88
|
||||
#define QUP_I2C_START_AND_STOP_SEQ 0x8A
|
||||
#define QUP_I2C_NOP_PADDING 0x97
|
||||
|
||||
#define OUT_FIFO_WR_TAG_BYTE_CNT 4
|
||||
#define OUT_FIFO_RD_TAG_BYTE_CNT 8
|
||||
#define IN_FIFO_TAG_BYTE_CNT 2
|
||||
#define OFFSET_BYTE_CNT 2
|
||||
|
||||
#define QUP_I2C_ADDR(x) ((x & 0xFF) << 1)
|
||||
#define QUP_I2C_DATA(x) (x & 0xFF)
|
||||
|
||||
enum dir {
|
||||
READ,
|
||||
WRITE,
|
||||
};
|
||||
|
||||
/* I2C some pre-defined frequencies */
|
||||
#define I2C_CLK_1KHZ 1
|
||||
#define I2C_CLK_100KHZ 100
|
||||
#define I2C_CLK_400KHZ 400
|
||||
#define I2C_CLK_1MHZ 1000
|
||||
#define QUP_INPUT_CLK_TCXO 19200
|
||||
#define QUP_INPUT_CLK QUP_INPUT_CLK_TCXO
|
||||
#define I2C_INPUT_CLK_TCXO_DIV4 ((I2C_INPUT_CLK_TCXO)/4)
|
||||
Loading…
Add table
Reference in a new issue