[linux] Upgrade the MMF SDK from V4.0.0 to V4.1.0
1. 181x support secureboot 2. add .gitignore Change-Id: I34cd45663d92eeb8e3b5ddfbf1a876111ce46bd1
This commit is contained in:
committed by
sam.xiang
parent
221f3d937b
commit
95dcbe5649
2
linux_5.10/.gitignore
vendored
Normal file
2
linux_5.10/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
build/
|
||||
scripts/dtc/include-prefixes/cvi_board_memmap.h
|
||||
@ -370,6 +370,16 @@ config ARCH_CV181X
|
||||
help
|
||||
This enables support for Cvitek's CV181X
|
||||
|
||||
config ARCH_ATHENA2
|
||||
bool "Cvitek ATHENA2 SoC"
|
||||
select PINCTRL
|
||||
select PINCTRL_BM
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
select GENERIC_PINCONF
|
||||
help
|
||||
This enables support for Cvitek's ATHENA2
|
||||
|
||||
config ARCH_CV952X
|
||||
bool "Cvitek CV952X SoC"
|
||||
select PINCTRL
|
||||
@ -476,6 +486,39 @@ config ARCH_CV181X_ASIC
|
||||
endchoice
|
||||
endif # end ARCH_CV181X
|
||||
|
||||
if ARCH_ATHENA2
|
||||
config ARCH_CVITEK_CHIP
|
||||
string "athena2"
|
||||
help
|
||||
This enables support for Cvitek ATHENA2 series
|
||||
|
||||
choice
|
||||
prompt "Select the platform of SoC"
|
||||
default ARCH_ATHENA2_FPGA
|
||||
help
|
||||
Select the platform of SoC
|
||||
FPGA
|
||||
PALLADIUM
|
||||
ASIC
|
||||
|
||||
config ARCH_ATHENA2_PALLADIUM
|
||||
bool "Cvitek ATHENA2 SoC - Palladium"
|
||||
help
|
||||
This enables support for Cvitek's ATHENA2 SoC on Palladium platform
|
||||
|
||||
config ARCH_ATHENA2_FPGA
|
||||
bool "Cvitek ATHENA2 SoC - FPGA"
|
||||
help
|
||||
This enables support for Cvitek's ATHENA2 SoC on FPGA platform
|
||||
|
||||
config ARCH_ATHENA2_ASIC
|
||||
bool "Cvitek ATHENA2 SoC- ASIC"
|
||||
help
|
||||
This enables support for Cvitek's ATHENA2 SoC ASIC
|
||||
|
||||
endchoice
|
||||
endif # end ARCH_ATHENA2
|
||||
|
||||
if ARCH_CV952X
|
||||
config ARCH_CVITEK_CHIP
|
||||
string "cv952x"
|
||||
|
||||
@ -235,4 +235,6 @@ source "drivers/interconnect/Kconfig"
|
||||
source "drivers/counter/Kconfig"
|
||||
|
||||
source "drivers/most/Kconfig"
|
||||
|
||||
source "drivers/efuse/Kconfig"
|
||||
endmenu
|
||||
|
||||
@ -189,3 +189,4 @@ obj-$(CONFIG_GNSS) += gnss/
|
||||
obj-$(CONFIG_INTERCONNECT) += interconnect/
|
||||
obj-$(CONFIG_COUNTER) += counter/
|
||||
obj-$(CONFIG_MOST) += most/
|
||||
obj-$(CONFIG_EFUSE) += efuse/
|
||||
|
||||
37
linux_5.10/drivers/efuse/Kconfig
Normal file
37
linux_5.10/drivers/efuse/Kconfig
Normal file
@ -0,0 +1,37 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Generic efuse drivers configuration
|
||||
#
|
||||
|
||||
menuconfig EFUSE
|
||||
bool "Efuse drivers"
|
||||
default y
|
||||
help
|
||||
Efuse drivers offer a generic mechanism for
|
||||
efuse management.
|
||||
Only support cv181x and cv180x currently
|
||||
Efuse driver build-in is better
|
||||
|
||||
if EFUSE
|
||||
|
||||
config CV181X_EFUSE
|
||||
tristate "Efuse driver for CVITEK CV181X"
|
||||
depends on ARCH_CV181X || COMPILE_TEST
|
||||
default y
|
||||
help
|
||||
Select this driver for CVITEK CV181X efuse
|
||||
This driver is used for program and read efuse
|
||||
This driver can also be built as a module
|
||||
But build-in is better.
|
||||
|
||||
config CV180X_EFUSE
|
||||
tristate "Efuse driver for CVITEK CV180X"
|
||||
depends on ARCH_CV180X || COMPILE_TEST
|
||||
default y
|
||||
help
|
||||
Select this driver for CVITEK CV180X efuse op
|
||||
This driver is used for program and read efuse
|
||||
This driver can also be built as a module
|
||||
But build-in is better.
|
||||
|
||||
endif
|
||||
9
linux_5.10/drivers/efuse/Makefile
Normal file
9
linux_5.10/drivers/efuse/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Makefile for sensor chip drivers.
|
||||
#
|
||||
|
||||
# platform efuse drivers
|
||||
obj-$(CONFIG_CV181X_EFUSE) += cv181x_efuse.o
|
||||
obj-$(CONFIG_CV180X_EFUSE) += cv180x_efuse.o
|
||||
|
||||
267
linux_5.10/drivers/efuse/cv180x_efuse.c
Normal file
267
linux_5.10/drivers/efuse/cv180x_efuse.c
Normal file
@ -0,0 +1,267 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// EFUSE implementation
|
||||
//
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/module.h>
|
||||
#include "linux/cv180x_efuse.h"
|
||||
|
||||
#define ERROR(fmt, ...) pr_err(fmt, ##__VA_ARGS__)
|
||||
#define VERBOSE(fmt, ...) pr_debug(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define EFUSE_BASE (0x03050000)
|
||||
|
||||
#define EFUSE_SHADOW_REG (efuse_base + 0x100)
|
||||
#define EFUSE_SIZE 0x100
|
||||
|
||||
#define EFUSE_MODE (efuse_base + 0x0)
|
||||
#define EFUSE_ADR (efuse_base + 0x4)
|
||||
#define EFUSE_DIR_CMD (efuse_base + 0x8)
|
||||
#define EFUSE_RD_DATA (efuse_base + 0xC)
|
||||
#define EFUSE_STATUS (efuse_base + 0x10)
|
||||
#define EFUSE_ONE_WAY (efuse_base + 0x14)
|
||||
|
||||
#define EFUSE_BIT_AREAD BIT(0)
|
||||
#define EFUSE_BIT_MREAD BIT(1)
|
||||
#define EFUSE_BIT_PRG BIT(2)
|
||||
#define EFUSE_BIT_PWR_DN BIT(3)
|
||||
#define EFUSE_BIT_CMD BIT(4)
|
||||
#define EFUSE_BIT_BUSY BIT(0)
|
||||
#define EFUSE_CMD_REFRESH (0x30)
|
||||
|
||||
enum EFUSE_READ_TYPE { EFUSE_AREAD, EFUSE_MREAD };
|
||||
|
||||
static void __iomem *efuse_base;
|
||||
static struct clk *efuse_clk;
|
||||
|
||||
static inline void mmio_write_32(void __iomem *addr, uint32_t value)
|
||||
{
|
||||
iowrite32(value, addr);
|
||||
}
|
||||
|
||||
static inline uint32_t mmio_read_32(void __iomem *addr)
|
||||
{
|
||||
return ioread32(addr);
|
||||
}
|
||||
|
||||
static inline void mmio_setbits_32(void __iomem *addr, uint32_t set)
|
||||
{
|
||||
mmio_write_32(addr, mmio_read_32(addr) | set);
|
||||
}
|
||||
|
||||
void cvi_efuse_wait_for_ready(void)
|
||||
{
|
||||
while (mmio_read_32(EFUSE_STATUS) & EFUSE_BIT_BUSY)
|
||||
;
|
||||
}
|
||||
|
||||
static void cvi_efuse_power_on(uint32_t on)
|
||||
{
|
||||
if (on)
|
||||
mmio_setbits_32(EFUSE_MODE, EFUSE_BIT_CMD);
|
||||
else
|
||||
mmio_setbits_32(EFUSE_MODE, EFUSE_BIT_PWR_DN | EFUSE_BIT_CMD);
|
||||
}
|
||||
|
||||
static void cvi_efuse_refresh(void)
|
||||
{
|
||||
mmio_write_32(EFUSE_MODE, EFUSE_CMD_REFRESH);
|
||||
}
|
||||
|
||||
static void cvi_efuse_prog_bit(uint32_t word_addr, uint32_t bit_addr,
|
||||
uint32_t high_row)
|
||||
{
|
||||
uint32_t phy_addr;
|
||||
|
||||
// word_addr: virtual addr, take "lower 6-bits" from 7-bits (0-127)
|
||||
// bit_addr: virtual addr, 5-bits (0-31)
|
||||
|
||||
// composite physical addr[11:0] = [11:7]bit_addr + [6:0]word_addr
|
||||
phy_addr =
|
||||
((bit_addr & 0x1F) << 7) | ((word_addr & 0x3F) << 1) | high_row;
|
||||
|
||||
cvi_efuse_wait_for_ready();
|
||||
|
||||
// send efuse program cmd
|
||||
mmio_write_32(EFUSE_ADR, phy_addr);
|
||||
mmio_write_32(EFUSE_MODE, EFUSE_BIT_PRG | EFUSE_BIT_CMD);
|
||||
}
|
||||
|
||||
static uint32_t cvi_efuse_read_from_phy(uint32_t phy_word_addr,
|
||||
enum EFUSE_READ_TYPE type)
|
||||
{
|
||||
// power on efuse macro
|
||||
cvi_efuse_power_on(1);
|
||||
|
||||
cvi_efuse_wait_for_ready();
|
||||
|
||||
mmio_write_32(EFUSE_ADR, phy_word_addr);
|
||||
|
||||
if (type == EFUSE_AREAD) // array read
|
||||
mmio_write_32(EFUSE_MODE, EFUSE_BIT_AREAD | EFUSE_BIT_CMD);
|
||||
else if (type == EFUSE_MREAD) // margin read
|
||||
mmio_write_32(EFUSE_MODE, EFUSE_BIT_MREAD | EFUSE_BIT_CMD);
|
||||
else {
|
||||
ERROR("EFUSE: Unsupported read type!");
|
||||
return (uint32_t)-1;
|
||||
}
|
||||
|
||||
cvi_efuse_wait_for_ready();
|
||||
|
||||
return mmio_read_32(EFUSE_RD_DATA);
|
||||
}
|
||||
|
||||
static int cvi_efuse_write_word(uint32_t vir_word_addr, uint32_t val)
|
||||
{
|
||||
uint32_t i, j, row_val, zero_bit;
|
||||
uint32_t new_value;
|
||||
int err_cnt = 0;
|
||||
|
||||
for (j = 0; j < 2; j++) {
|
||||
VERBOSE("EFUSE: Program physical word addr #%d\n",
|
||||
(vir_word_addr << 1) | j);
|
||||
|
||||
// array read by word address
|
||||
row_val = cvi_efuse_read_from_phy(
|
||||
(vir_word_addr << 1) | j,
|
||||
EFUSE_AREAD); // read low word of word_addr
|
||||
zero_bit = val & (~row_val); // only program zero bit
|
||||
|
||||
// program row which bit is zero
|
||||
for (i = 0; i < 32; i++) {
|
||||
if ((zero_bit >> i) & 1)
|
||||
cvi_efuse_prog_bit(vir_word_addr, i, j);
|
||||
}
|
||||
|
||||
// check by margin read
|
||||
new_value = cvi_efuse_read_from_phy((vir_word_addr << 1) | j,
|
||||
EFUSE_MREAD);
|
||||
VERBOSE("%s(): val=0x%x new_value=0x%x\n", __func__, val,
|
||||
new_value);
|
||||
if ((val & new_value) != val) {
|
||||
err_cnt += 1;
|
||||
ERROR("EFUSE: Program bits check failed (%d)!\n",
|
||||
err_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
cvi_efuse_refresh();
|
||||
|
||||
return err_cnt >= 2 ? -EIO : 0;
|
||||
}
|
||||
|
||||
int __init cvi_efuse_init(void)
|
||||
{
|
||||
efuse_base = ioremap(EFUSE_BASE, 0x1000);
|
||||
if (efuse_base == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
efuse_clk = clk_get_sys(NULL, "clk_efuse");
|
||||
if (IS_ERR(efuse_clk)) {
|
||||
pr_err("%s: efuse clock not found %ld\n", __func__,
|
||||
PTR_ERR(efuse_clk));
|
||||
return PTR_ERR(efuse_clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit cvi_efuse_exit(void)
|
||||
{
|
||||
iounmap(efuse_base);
|
||||
}
|
||||
|
||||
int64_t cvi_efuse_read_from_shadow(uint32_t addr)
|
||||
{
|
||||
int64_t ret = -1;
|
||||
|
||||
if (addr >= EFUSE_SIZE)
|
||||
return -EFAULT;
|
||||
|
||||
if (addr % 4 != 0)
|
||||
return -EFAULT;
|
||||
|
||||
ret = clk_prepare_enable(efuse_clk);
|
||||
if (ret) {
|
||||
pr_err("%s: clock failed to prepare+enable: %lld\n", __func__,
|
||||
(long long)ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mmio_read_32(EFUSE_SHADOW_REG + addr);
|
||||
clk_disable_unprepare(efuse_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cvi_efuse_read_from_shadow);
|
||||
|
||||
int cvi_efuse_write(uint32_t addr, uint32_t value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
VERBOSE("%s(): 0x%x = 0x%x\n", __func__, addr, value);
|
||||
|
||||
if (addr >= EFUSE_SIZE)
|
||||
return -EFAULT;
|
||||
|
||||
if (addr % 4 != 0)
|
||||
return -EFAULT;
|
||||
|
||||
ret = clk_prepare_enable(efuse_clk);
|
||||
if (ret) {
|
||||
pr_err("%s: clock failed to prepare+enable: %lld\n", __func__,
|
||||
(long long)ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = cvi_efuse_write_word(addr / 4, value);
|
||||
VERBOSE("%s(): ret=%d\n", __func__, ret);
|
||||
|
||||
cvi_efuse_power_on(1);
|
||||
cvi_efuse_refresh();
|
||||
cvi_efuse_wait_for_ready();
|
||||
|
||||
clk_disable_unprepare(efuse_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cvi_efuse_write);
|
||||
|
||||
int cvi_efuse_read_buf(u32 addr, void *buf, size_t buf_size)
|
||||
{
|
||||
int64_t ret = -1;
|
||||
int i;
|
||||
|
||||
if (!buf)
|
||||
return -EFAULT;
|
||||
|
||||
if (buf_size > EFUSE_SIZE)
|
||||
buf_size = EFUSE_SIZE;
|
||||
|
||||
memset(buf, 0, buf_size);
|
||||
|
||||
for (i = 0; i < buf_size; i += 4) {
|
||||
ret = cvi_efuse_read_from_shadow(addr + i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret > 0) {
|
||||
u32 v = ret;
|
||||
|
||||
memcpy(buf + i, &v, sizeof(v));
|
||||
}
|
||||
}
|
||||
|
||||
return buf_size;
|
||||
}
|
||||
EXPORT_SYMBOL(cvi_efuse_read_buf);
|
||||
|
||||
module_init(cvi_efuse_init);
|
||||
module_exit(cvi_efuse_exit);
|
||||
|
||||
MODULE_AUTHOR("leon.liao@cvitek.com");
|
||||
MODULE_DESCRIPTION("cv180x efuse driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
268
linux_5.10/drivers/efuse/cv181x_efuse.c
Normal file
268
linux_5.10/drivers/efuse/cv181x_efuse.c
Normal file
@ -0,0 +1,268 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// EFUSE implementation
|
||||
//
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "linux/cv180x_efuse.h"
|
||||
|
||||
#define ERROR(fmt, ...) pr_err(fmt, ##__VA_ARGS__)
|
||||
#define VERBOSE(fmt, ...) pr_debug(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define EFUSE_BASE (0x03050000)
|
||||
|
||||
#define EFUSE_SHADOW_REG (efuse_base + 0x100)
|
||||
#define EFUSE_SIZE 0x100
|
||||
|
||||
#define EFUSE_MODE (efuse_base + 0x0)
|
||||
#define EFUSE_ADR (efuse_base + 0x4)
|
||||
#define EFUSE_DIR_CMD (efuse_base + 0x8)
|
||||
#define EFUSE_RD_DATA (efuse_base + 0xC)
|
||||
#define EFUSE_STATUS (efuse_base + 0x10)
|
||||
#define EFUSE_ONE_WAY (efuse_base + 0x14)
|
||||
|
||||
#define EFUSE_BIT_AREAD BIT(0)
|
||||
#define EFUSE_BIT_MREAD BIT(1)
|
||||
#define EFUSE_BIT_PRG BIT(2)
|
||||
#define EFUSE_BIT_PWR_DN BIT(3)
|
||||
#define EFUSE_BIT_CMD BIT(4)
|
||||
#define EFUSE_BIT_BUSY BIT(0)
|
||||
#define EFUSE_CMD_REFRESH (0x30)
|
||||
|
||||
enum EFUSE_READ_TYPE { EFUSE_AREAD, EFUSE_MREAD };
|
||||
|
||||
static void __iomem *efuse_base;
|
||||
static struct clk *efuse_clk;
|
||||
|
||||
static inline void mmio_write_32(void __iomem *addr, uint32_t value)
|
||||
{
|
||||
iowrite32(value, addr);
|
||||
}
|
||||
|
||||
static inline uint32_t mmio_read_32(void __iomem *addr)
|
||||
{
|
||||
return ioread32(addr);
|
||||
}
|
||||
|
||||
static inline void mmio_setbits_32(void __iomem *addr, uint32_t set)
|
||||
{
|
||||
mmio_write_32(addr, mmio_read_32(addr) | set);
|
||||
}
|
||||
|
||||
void cvi_efuse_wait_for_ready(void)
|
||||
{
|
||||
while (mmio_read_32(EFUSE_STATUS) & EFUSE_BIT_BUSY)
|
||||
;
|
||||
}
|
||||
|
||||
static void cvi_efuse_power_on(uint32_t on)
|
||||
{
|
||||
if (on)
|
||||
mmio_setbits_32(EFUSE_MODE, EFUSE_BIT_CMD);
|
||||
else
|
||||
mmio_setbits_32(EFUSE_MODE, EFUSE_BIT_PWR_DN | EFUSE_BIT_CMD);
|
||||
}
|
||||
|
||||
static void cvi_efuse_refresh(void)
|
||||
{
|
||||
mmio_write_32(EFUSE_MODE, EFUSE_CMD_REFRESH);
|
||||
}
|
||||
|
||||
static void cvi_efuse_prog_bit(uint32_t word_addr, uint32_t bit_addr,
|
||||
uint32_t high_row)
|
||||
{
|
||||
uint32_t phy_addr;
|
||||
|
||||
// word_addr: virtual addr, take "lower 6-bits" from 7-bits (0-127)
|
||||
// bit_addr: virtual addr, 5-bits (0-31)
|
||||
|
||||
// composite physical addr[11:0] = [11:7]bit_addr + [6:0]word_addr
|
||||
phy_addr =
|
||||
((bit_addr & 0x1F) << 7) | ((word_addr & 0x3F) << 1) | high_row;
|
||||
|
||||
cvi_efuse_wait_for_ready();
|
||||
|
||||
// send efuse program cmd
|
||||
mmio_write_32(EFUSE_ADR, phy_addr);
|
||||
mmio_write_32(EFUSE_MODE, EFUSE_BIT_PRG | EFUSE_BIT_CMD);
|
||||
}
|
||||
|
||||
static uint32_t cvi_efuse_read_from_phy(uint32_t phy_word_addr,
|
||||
enum EFUSE_READ_TYPE type)
|
||||
{
|
||||
// power on efuse macro
|
||||
cvi_efuse_power_on(1);
|
||||
|
||||
cvi_efuse_wait_for_ready();
|
||||
|
||||
mmio_write_32(EFUSE_ADR, phy_word_addr);
|
||||
|
||||
if (type == EFUSE_AREAD) // array read
|
||||
mmio_write_32(EFUSE_MODE, EFUSE_BIT_AREAD | EFUSE_BIT_CMD);
|
||||
else if (type == EFUSE_MREAD) // margin read
|
||||
mmio_write_32(EFUSE_MODE, EFUSE_BIT_MREAD | EFUSE_BIT_CMD);
|
||||
else {
|
||||
ERROR("EFUSE: Unsupported read type!");
|
||||
return (uint32_t)-1;
|
||||
}
|
||||
|
||||
cvi_efuse_wait_for_ready();
|
||||
|
||||
return mmio_read_32(EFUSE_RD_DATA);
|
||||
}
|
||||
|
||||
static int cvi_efuse_write_word(uint32_t vir_word_addr, uint32_t val)
|
||||
{
|
||||
uint32_t i, j, row_val, zero_bit;
|
||||
uint32_t new_value;
|
||||
int err_cnt = 0;
|
||||
|
||||
for (j = 0; j < 2; j++) {
|
||||
VERBOSE("EFUSE: Program physical word addr #%d\n",
|
||||
(vir_word_addr << 1) | j);
|
||||
|
||||
// array read by word address
|
||||
row_val = cvi_efuse_read_from_phy(
|
||||
(vir_word_addr << 1) | j,
|
||||
EFUSE_AREAD); // read low word of word_addr
|
||||
zero_bit = val & (~row_val); // only program zero bit
|
||||
|
||||
// program row which bit is zero
|
||||
for (i = 0; i < 32; i++) {
|
||||
if ((zero_bit >> i) & 1)
|
||||
cvi_efuse_prog_bit(vir_word_addr, i, j);
|
||||
}
|
||||
|
||||
// check by margin read
|
||||
new_value = cvi_efuse_read_from_phy((vir_word_addr << 1) | j,
|
||||
EFUSE_MREAD);
|
||||
VERBOSE("%s(): val=0x%x new_value=0x%x\n", __func__, val,
|
||||
new_value);
|
||||
if ((val & new_value) != val) {
|
||||
err_cnt += 1;
|
||||
ERROR("EFUSE: Program bits check failed (%d)!\n",
|
||||
err_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
cvi_efuse_refresh();
|
||||
|
||||
return err_cnt >= 2 ? -EIO : 0;
|
||||
}
|
||||
|
||||
int __init cvi_efuse_init(void)
|
||||
{
|
||||
efuse_base = ioremap(EFUSE_BASE, 0x1000);
|
||||
if (efuse_base == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
efuse_clk = clk_get_sys(NULL, "clk_efuse");
|
||||
if (IS_ERR(efuse_clk)) {
|
||||
pr_err("%s: efuse clock not found %ld\n", __func__,
|
||||
PTR_ERR(efuse_clk));
|
||||
return PTR_ERR(efuse_clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit cvi_efuse_exit(void)
|
||||
{
|
||||
iounmap(efuse_base);
|
||||
}
|
||||
|
||||
int64_t cvi_efuse_read_from_shadow(uint32_t addr)
|
||||
{
|
||||
int64_t ret = -1;
|
||||
|
||||
if (addr >= EFUSE_SIZE)
|
||||
return -EFAULT;
|
||||
|
||||
if (addr % 4 != 0)
|
||||
return -EFAULT;
|
||||
|
||||
ret = clk_prepare_enable(efuse_clk);
|
||||
if (ret) {
|
||||
pr_err("%s: clock failed to prepare+enable: %lld\n", __func__,
|
||||
(long long)ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mmio_read_32(EFUSE_SHADOW_REG + addr);
|
||||
clk_disable_unprepare(efuse_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cvi_efuse_read_from_shadow);
|
||||
|
||||
int cvi_efuse_write(uint32_t addr, uint32_t value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
VERBOSE("%s(): 0x%x = 0x%x\n", __func__, addr, value);
|
||||
|
||||
if (addr >= EFUSE_SIZE)
|
||||
return -EFAULT;
|
||||
|
||||
if (addr % 4 != 0)
|
||||
return -EFAULT;
|
||||
|
||||
ret = clk_prepare_enable(efuse_clk);
|
||||
if (ret) {
|
||||
pr_err("%s: clock failed to prepare+enable: %lld\n", __func__,
|
||||
(long long)ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = cvi_efuse_write_word(addr / 4, value);
|
||||
VERBOSE("%s(): ret=%d\n", __func__, ret);
|
||||
|
||||
cvi_efuse_power_on(1);
|
||||
cvi_efuse_refresh();
|
||||
cvi_efuse_wait_for_ready();
|
||||
|
||||
clk_disable_unprepare(efuse_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cvi_efuse_write);
|
||||
|
||||
int cvi_efuse_read_buf(u32 addr, void *buf, size_t buf_size)
|
||||
{
|
||||
int64_t ret = -1;
|
||||
int i;
|
||||
|
||||
if (!buf)
|
||||
return -EFAULT;
|
||||
|
||||
if (buf_size > EFUSE_SIZE)
|
||||
buf_size = EFUSE_SIZE;
|
||||
|
||||
memset(buf, 0, buf_size);
|
||||
|
||||
for (i = 0; i < buf_size; i += 4) {
|
||||
ret = cvi_efuse_read_from_shadow(addr + i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret > 0) {
|
||||
u32 v = ret;
|
||||
|
||||
memcpy(buf + i, &v, sizeof(v));
|
||||
}
|
||||
}
|
||||
|
||||
return buf_size;
|
||||
}
|
||||
EXPORT_SYMBOL(cvi_efuse_read_buf);
|
||||
|
||||
module_init(cvi_efuse_init);
|
||||
module_exit(cvi_efuse_exit);
|
||||
|
||||
MODULE_AUTHOR("leon.liao@cvitek.com");
|
||||
MODULE_DESCRIPTION("cv180x efuse driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@ -157,6 +157,12 @@ static const struct flash_info cvitek_parts[] = {
|
||||
{ "FM25Q64", INFO(0xF83217, 0x0, 64 * 1024, 128,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_OP)
|
||||
.fixups = &sr_bit1_qe_fixups },
|
||||
{ "FM25Q128A", INFO(0xA14018, 0x0, 64 * 1024, 256,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_OP)
|
||||
.fixups = &sr_bit1_qe_fixups },
|
||||
{ "FM25W128A", INFO(0xA12818, 0x0, 64 * 1024, 256,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_OP)
|
||||
.fixups = &sr_bit1_qe_fixups },
|
||||
{ "BY25Q128AS", INFO(0x684018, 0x0, 64 * 1024, 256,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_OP)
|
||||
.fixups = &sr_bit1_qe_fixups },
|
||||
|
||||
@ -158,11 +158,11 @@ config CICADA_PHY
|
||||
help
|
||||
Currently supports the cis8204
|
||||
|
||||
config CV182XA_PHY
|
||||
tristate "CV182XA PHYs"
|
||||
config CVITEK_PHY
|
||||
tristate "CVITEK PHYs"
|
||||
help
|
||||
Enable support for RMII PHYs manufactured by CVITEK
|
||||
Include driver for cv182xa.
|
||||
Include driver for cvitek.
|
||||
This is an internal ethernet phy.
|
||||
And support 100Mbs full duplex.
|
||||
|
||||
|
||||
@ -48,7 +48,6 @@ obj-$(CONFIG_BCM_CYGNUS_PHY) += bcm-cygnus.o
|
||||
obj-$(CONFIG_BCM_NET_PHYLIB) += bcm-phy-lib.o
|
||||
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
|
||||
obj-$(CONFIG_CICADA_PHY) += cicada.o
|
||||
obj-$(CONFIG_CV182XA_PHY) += cv182xa.o
|
||||
obj-$(CONFIG_CVITEK_PHY) += cvitek.o
|
||||
obj-$(CONFIG_CORTINA_PHY) += cortina.o
|
||||
obj-$(CONFIG_DAVICOM_PHY) += davicom.o
|
||||
|
||||
@ -8,136 +8,53 @@
|
||||
#include <linux/phy.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/cv180x_efuse.h>
|
||||
|
||||
#define CVI_ETH_PHY_ADC_CTRL 16
|
||||
#define CVI_ETH_PHY_INT_STS 16
|
||||
#define CVI_ETH_AUTO_CALIBRATE 16
|
||||
#define CVI_ETH_PHY_INT_MASK 17
|
||||
#define CVI_ETH_PHY_APS 18
|
||||
#define CVI_ETH_PHY_UAPS 19
|
||||
#define CVI_ETH_PHY_LB_CTL 18
|
||||
#define CVI_ETH_PHY_AFE_TX 20
|
||||
#define CVI_ETH_PHY_AFE_DRV2 21
|
||||
#define CVI_ETH_PHY_CP 23
|
||||
#define CVI_ETH_PHY_ADC_OP_BIAS 24
|
||||
#define CVI_ETH_PHY_STATUS 25
|
||||
#define CVI_ETH_PHY_RX_SIGNAL 25
|
||||
#define CVI_ETH_PHY_2_MISC 28
|
||||
#define CVI_ETH_PHY_TXDATA_CTRL 24
|
||||
#define CVI_ETH_PHY_PAGE_SEL 31
|
||||
|
||||
#define CVI_ETH_PHY_PAGE_0 0x0000
|
||||
#define CVI_ETH_PHY_PAGE_1 0x0100
|
||||
#define CVI_ETH_PHY_PAGE_2 0x0200
|
||||
#define CVI_ETH_PHY_PAGE_3 0x0300
|
||||
#define CVI_ETH_PHY_PAGE_6 0x0600
|
||||
#define CVI_ETH_PHY_PAGE_8 0x0800
|
||||
#define CVI_ETH_PHY_PAGE_9 0x0900
|
||||
|
||||
#define CVI_ETH_PHY_LOOPBACK
|
||||
#define LOOPBACK_XMII2MAC 0x8000
|
||||
#define LOOPBACK_PCS2MAC 0x2000
|
||||
#define LOOPBACK_PMA2MAC 0x1000
|
||||
#define LOOPBACK_RMII2PHY 0x0080
|
||||
|
||||
#define CVI_LNK_STS_CHG_INT_MSK BIT(15)
|
||||
#define CVI_MGC_PKT_DET_INT_MSK BIT(14)
|
||||
#define CVI_TX_LPI_RCV_INT_MSK BIT(13)
|
||||
#define CVI_RX_LPI_RCV_INT_MSK BIT(12)
|
||||
|
||||
#define CVI_UAPS_ENABLE BIT(15)
|
||||
|
||||
#define CVI_CKSELIN BIT(13)
|
||||
#define REG_EPHY_TOP_WRAP 0x03009800
|
||||
#define REG_EPHY_BASE 0x03009000
|
||||
#define EPHY_EFUSE_TXECHORC_FLAG 0x00000100 // bit 8
|
||||
#define EPHY_EFUSE_TXITUNE_FLAG 0x00000200 // bit 9
|
||||
#define EPHY_EFUSE_TXRXTERM_FLAG 0x00000800 // bit 11
|
||||
|
||||
#define CVI_INT_EVENTS \
|
||||
(CVI_LNK_STS_CHG_INT_MSK | CVI_MGC_PKT_DET_INT_MSK)
|
||||
|
||||
static int cvi_phy_config_intr(struct phy_device *phydev)
|
||||
static int cv182xa_phy_config_intr(struct phy_device *phydev)
|
||||
{
|
||||
int rc = phy_write(phydev, CVI_ETH_PHY_INT_MASK,
|
||||
((phydev->interrupts == PHY_INTERRUPT_ENABLED)
|
||||
? CVI_INT_EVENTS
|
||||
: 0));
|
||||
return rc < 0 ? rc : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cvi_phy_ack_interrupt(struct phy_device *phydev)
|
||||
static int cv182xa_phy_ack_interrupt(struct phy_device *phydev)
|
||||
{
|
||||
int err;
|
||||
|
||||
pr_debug("%s, clear interrupts\n", __func__);
|
||||
err = phy_write(phydev, CVI_ETH_PHY_INT_STS, 0xf000);
|
||||
|
||||
return err < 0 ? err : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cvi_read_status(struct phy_device *phydev)
|
||||
static int cv182xa_read_status(struct phy_device *phydev)
|
||||
{
|
||||
int err = genphy_read_status(phydev);
|
||||
|
||||
pr_debug("%s, speed=%d, duplex=%d, ", __func__, phydev->speed, phydev->duplex);
|
||||
pr_debug("pasue=%d, asym_pause=%d, autoneg=%d ", phydev->pause, phydev->asym_pause, phydev->autoneg);
|
||||
pr_debug("cvi_Status=0x%04x\n", phy_read(phydev, CVI_ETH_PHY_STATUS));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CVITEK_PHY_UAPS)
|
||||
/* Ultra Auto Power Saving mode */
|
||||
static int cvi_phy_aps_enable(struct phy_device *phydev)
|
||||
static int cv182xa_phy_aps_enable(struct phy_device *phydev)
|
||||
{
|
||||
int val;
|
||||
|
||||
pr_info("Enable CVITEK ethernet phy ultra auto power saving mode\n");
|
||||
phy_write(phydev, CVI_ETH_PHY_PAGE_SEL, CVI_ETH_PHY_PAGE_1);
|
||||
|
||||
val = phy_read(phydev, CVI_ETH_PHY_UAPS);
|
||||
phy_write(phydev, CVI_ETH_PHY_UAPS, CVI_UAPS_ENABLE | val);
|
||||
phy_write(phydev, CVI_ETH_PHY_PAGE_SEL, CVI_ETH_PHY_PAGE_0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int cvi_phy_config_aneg(struct phy_device *phydev)
|
||||
static int cv182xa_phy_config_aneg(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* switch to page 1 */
|
||||
phy_write(phydev, CVI_ETH_PHY_PAGE_SEL, CVI_ETH_PHY_PAGE_1);
|
||||
/* Disable APS */
|
||||
phy_write(phydev, CVI_ETH_PHY_APS, 0x4824);
|
||||
/* switch to page 2 */
|
||||
phy_write(phydev, CVI_ETH_PHY_PAGE_SEL, CVI_ETH_PHY_PAGE_2);
|
||||
/* PHYAFE TRX optimization */
|
||||
phy_write(phydev, CVI_ETH_PHY_TXDATA_CTRL, 0x0000);
|
||||
/* switch to page 6 */
|
||||
phy_write(phydev, CVI_ETH_PHY_PAGE_SEL, CVI_ETH_PHY_PAGE_6);
|
||||
/* PHYAFE ADC optimization */
|
||||
phy_write(phydev, CVI_ETH_PHY_ADC_CTRL, 0x555b);
|
||||
/* PHYAFE TX optimization */
|
||||
phy_write(phydev, CVI_ETH_PHY_AFE_TX, 0x508f);
|
||||
/* enable a_CLKSELIN to avoid CRC error and increase 10M/100M amplitude*/
|
||||
phy_write(phydev, CVI_ETH_PHY_AFE_DRV2, 0x3030);
|
||||
/* PHYAFE CP current optimization */
|
||||
phy_write(phydev, CVI_ETH_PHY_CP, 0x0575);
|
||||
/* PHYAFE ADC OP BIAS optimization */
|
||||
phy_write(phydev, CVI_ETH_PHY_ADC_OP_BIAS, 0x0000);
|
||||
/* PHYAFE RX signal detector level optimization */
|
||||
phy_write(phydev, CVI_ETH_PHY_RX_SIGNAL, 0x0408);
|
||||
/* Enable PD control optimization */
|
||||
phy_write(phydev, CVI_ETH_PHY_2_MISC, 0x8880);
|
||||
|
||||
/* switch to page 8 */
|
||||
phy_write(phydev, CVI_ETH_PHY_PAGE_SEL, CVI_ETH_PHY_PAGE_8);
|
||||
/* Stop auto-calibrate */
|
||||
phy_write(phydev, CVI_ETH_AUTO_CALIBRATE, 0x0844);
|
||||
|
||||
#if defined(CONFIG_CVITEK_PHY_UAPS)
|
||||
cvi_phy_aps_enable(phydev); /* if phy not work, disable this function for try */
|
||||
cv182xa_phy_aps_enable(phydev); /* if phy not work, disable this function for try */
|
||||
#endif
|
||||
/* switch back to page 0 */
|
||||
phy_write(phydev, CVI_ETH_PHY_PAGE_SEL, CVI_ETH_PHY_PAGE_0);
|
||||
|
||||
ret = genphy_config_aneg(phydev);
|
||||
|
||||
@ -147,42 +64,310 @@ static int cvi_phy_config_aneg(struct phy_device *phydev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cvi_phy_config_init(struct phy_device *phydev)
|
||||
static int cv182xa_phy_config_init(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
u32 val = 0;
|
||||
void __iomem *reg_ephy_top_wrap = NULL;
|
||||
void __iomem *reg_ephy_base = NULL;
|
||||
|
||||
ret = genphy_read_abilities(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
reg_ephy_top_wrap = ioremap(REG_EPHY_TOP_WRAP, 0x8);
|
||||
if (!reg_ephy_top_wrap) {
|
||||
ret = -EBUSY;
|
||||
goto err_ephy_mem_1;
|
||||
}
|
||||
reg_ephy_base = ioremap(REG_EPHY_BASE, 0x80);
|
||||
if (!reg_ephy_base) {
|
||||
ret = -EBUSY;
|
||||
goto err_ephy_mem_2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
// set rg_ephy_apb_rw_sel 0x0804@[0]=1/APB by using APB interface
|
||||
writel(0x0001, reg_ephy_top_wrap + 4);
|
||||
|
||||
writel(0x0, reg_ephy_base + 0x7c);
|
||||
|
||||
/* do this in board.c */
|
||||
// Release 0x0800[0]=0/shutdown
|
||||
// writel(0x0900, reg_ephy_top_wrap);
|
||||
|
||||
// // Release 0x0800[2]=1/dig_rst_n, Let mii_reg can be accessabile
|
||||
// writel(0x0904, reg_ephy_top_wrap);
|
||||
|
||||
// //mdelay(10);
|
||||
|
||||
// // ANA INIT (PD/EN), switch to MII-page5
|
||||
// writel(0x0500, reg_ephy_base + 0x7c);
|
||||
// // Release ANA_PD p5.0x10@[13:8] = 6'b001100
|
||||
// writel(0x0c00, reg_ephy_base + 0x40);
|
||||
// // Release ANA_EN p5.0x10@[7:0] = 8'b01111110
|
||||
// writel(0x0c7e, reg_ephy_base + 0x40);
|
||||
|
||||
// // Wait PLL_Lock, Lock_Status p5.0x12@[15] = 1
|
||||
// //mdelay(1);
|
||||
|
||||
// // Release 0x0800[1] = 1/ana_rst_n
|
||||
// writel(0x0906, reg_ephy_top_wrap);
|
||||
|
||||
// // ANA INIT
|
||||
// // @Switch to MII-page5
|
||||
// writel(0x0500, reg_ephy_base + 0x7c);
|
||||
|
||||
// Efuse register
|
||||
// Set Double Bias Current
|
||||
//Set rg_eth_txitune1 reg_ephy_base + 0x64 [15:8]
|
||||
//Set rg_eth_txitune0 reg_ephy_base + 0x64 [7:0]
|
||||
if ((cvi_efuse_read_from_shadow(0x20) & EPHY_EFUSE_TXITUNE_FLAG) ==
|
||||
EPHY_EFUSE_TXITUNE_FLAG) {
|
||||
val = ((cvi_efuse_read_from_shadow(0x24) >> 24) & 0xFF) |
|
||||
(((cvi_efuse_read_from_shadow(0x24) >> 16) & 0xFF) << 8);
|
||||
writel((readl(reg_ephy_base + 0x64) & ~0xFFFF) | val, reg_ephy_base + 0x64);
|
||||
} else
|
||||
writel(0x5a5a, reg_ephy_base + 0x64);
|
||||
|
||||
// Set Echo_I
|
||||
// Set rg_eth_txechoiadj reg_ephy_base + 0x54 [15:8]
|
||||
if ((cvi_efuse_read_from_shadow(0x20) & EPHY_EFUSE_TXECHORC_FLAG) ==
|
||||
EPHY_EFUSE_TXECHORC_FLAG) {
|
||||
writel((readl(reg_ephy_base + 0x54) & ~0xFF00) |
|
||||
(((cvi_efuse_read_from_shadow(0x24) >> 8) & 0xFF) << 8), reg_ephy_base + 0x54);
|
||||
} else
|
||||
writel(0x0000, reg_ephy_base + 0x54);
|
||||
|
||||
//Set TX_Rterm & Echo_RC_Delay
|
||||
// Set rg_eth_txrterm_p1 reg_ephy_base + 0x58 [11:8]
|
||||
// Set rg_eth_txrterm reg_ephy_base + 0x58 [7:4]
|
||||
// Set rg_eth_txechorcadj reg_ephy_base + 0x58 [3:0]
|
||||
if ((cvi_efuse_read_from_shadow(0x20) & EPHY_EFUSE_TXRXTERM_FLAG) ==
|
||||
EPHY_EFUSE_TXRXTERM_FLAG) {
|
||||
val = (((cvi_efuse_read_from_shadow(0x20) >> 28) & 0xF) << 4) |
|
||||
(((cvi_efuse_read_from_shadow(0x20) >> 24) & 0xF) << 8);
|
||||
writel((readl(reg_ephy_base + 0x58) & ~0xFF0) | val, reg_ephy_base + 0x58);
|
||||
} else
|
||||
writel(0x0bb0, reg_ephy_base + 0x58);
|
||||
|
||||
// ETH_100BaseT
|
||||
// Set Rise update
|
||||
writel(0x0c10, reg_ephy_base + 0x5c);
|
||||
|
||||
// Set Falling phase
|
||||
writel(0x0003, reg_ephy_base + 0x68);
|
||||
|
||||
// Set Double TX Bias Current
|
||||
writel(0x0000, reg_ephy_base + 0x54);
|
||||
|
||||
// Switch to MII-page16
|
||||
writel(0x1000, reg_ephy_base + 0x7c);
|
||||
|
||||
// Set MLT3 Positive phase code, Set MLT3 +0
|
||||
writel(0x1000, reg_ephy_base + 0x68);
|
||||
writel(0x3020, reg_ephy_base + 0x6c);
|
||||
writel(0x5040, reg_ephy_base + 0x70);
|
||||
writel(0x7060, reg_ephy_base + 0x74);
|
||||
|
||||
// Set MLT3 +I
|
||||
writel(0x1708, reg_ephy_base + 0x58);
|
||||
writel(0x3827, reg_ephy_base + 0x5c);
|
||||
writel(0x5748, reg_ephy_base + 0x60);
|
||||
writel(0x7867, reg_ephy_base + 0x64);
|
||||
|
||||
// Switch to MII-page17
|
||||
writel(0x1100, reg_ephy_base + 0x7c);
|
||||
|
||||
// Set MLT3 Negative phase code, Set MLT3 -0
|
||||
writel(0x9080, reg_ephy_base + 0x40);
|
||||
writel(0xb0a0, reg_ephy_base + 0x44);
|
||||
writel(0xd0c0, reg_ephy_base + 0x48);
|
||||
writel(0xf0e0, reg_ephy_base + 0x4c);
|
||||
|
||||
// Set MLT3 -I
|
||||
writel(0x9788, reg_ephy_base + 0x50);
|
||||
writel(0xb8a7, reg_ephy_base + 0x54);
|
||||
writel(0xd7c8, reg_ephy_base + 0x58);
|
||||
writel(0xf8e7, reg_ephy_base + 0x5c);
|
||||
|
||||
// @Switch to MII-page5
|
||||
writel(0x0500, reg_ephy_base + 0x7c);
|
||||
|
||||
// En TX_Rterm
|
||||
writel((0x0001 | readl(reg_ephy_base + 0x40)), reg_ephy_base + 0x40);
|
||||
|
||||
// Link Pulse
|
||||
// Switch to MII-page10
|
||||
writel(0x0a00, reg_ephy_base + 0x7c);
|
||||
|
||||
// Set Link Pulse
|
||||
// writel(0x3e00, reg_ephy_base + 0x40);
|
||||
// writel(0x7864, reg_ephy_base + 0x44);
|
||||
// writel(0x6470, reg_ephy_base + 0x48);
|
||||
// writel(0x5f62, reg_ephy_base + 0x4c);
|
||||
// writel(0x5a5a, reg_ephy_base + 0x50);
|
||||
// writel(0x5458, reg_ephy_base + 0x54);
|
||||
// writel(0xb23a, reg_ephy_base + 0x58);
|
||||
// writel(0x94a0, reg_ephy_base + 0x5c);
|
||||
// writel(0x9092, reg_ephy_base + 0x60);
|
||||
// writel(0x8a8e, reg_ephy_base + 0x64);
|
||||
// writel(0x8688, reg_ephy_base + 0x68);
|
||||
// writel(0x8484, reg_ephy_base + 0x6c);
|
||||
// writel(0x0082, reg_ephy_base + 0x70);
|
||||
|
||||
// from sean
|
||||
// Fix err: the status is still linkup when removed the network cable.
|
||||
writel(0x2000, reg_ephy_base + 0x40);
|
||||
writel(0x3832, reg_ephy_base + 0x44);
|
||||
writel(0x3132, reg_ephy_base + 0x48);
|
||||
writel(0x2d2f, reg_ephy_base + 0x4c);
|
||||
writel(0x2c2d, reg_ephy_base + 0x50);
|
||||
writel(0x1b2b, reg_ephy_base + 0x54);
|
||||
writel(0x94a0, reg_ephy_base + 0x58);
|
||||
writel(0x8990, reg_ephy_base + 0x5c);
|
||||
writel(0x8788, reg_ephy_base + 0x60);
|
||||
writel(0x8485, reg_ephy_base + 0x64);
|
||||
writel(0x8283, reg_ephy_base + 0x68);
|
||||
writel(0x8182, reg_ephy_base + 0x6c);
|
||||
writel(0x0081, reg_ephy_base + 0x70);
|
||||
|
||||
// TP_IDLE
|
||||
// Switch to MII-page11
|
||||
writel(0x0b00, reg_ephy_base + 0x7c);
|
||||
|
||||
// Set TP_IDLE
|
||||
writel(0x5252, reg_ephy_base + 0x40);
|
||||
writel(0x5252, reg_ephy_base + 0x44);
|
||||
writel(0x4B52, reg_ephy_base + 0x48);
|
||||
writel(0x3D47, reg_ephy_base + 0x4c);
|
||||
writel(0xAA99, reg_ephy_base + 0x50);
|
||||
writel(0x989E, reg_ephy_base + 0x54);
|
||||
writel(0x9395, reg_ephy_base + 0x58);
|
||||
writel(0x9091, reg_ephy_base + 0x5c);
|
||||
writel(0x8E8F, reg_ephy_base + 0x60);
|
||||
writel(0x8D8E, reg_ephy_base + 0x64);
|
||||
writel(0x8C8C, reg_ephy_base + 0x68);
|
||||
writel(0x8B8B, reg_ephy_base + 0x6c);
|
||||
writel(0x008A, reg_ephy_base + 0x70);
|
||||
|
||||
// ETH 10BaseT Data
|
||||
// Switch to MII-page13
|
||||
writel(0x0d00, reg_ephy_base + 0x7c);
|
||||
|
||||
writel(0x1E0A, reg_ephy_base + 0x40);
|
||||
writel(0x3862, reg_ephy_base + 0x44);
|
||||
writel(0x1E62, reg_ephy_base + 0x48);
|
||||
writel(0x2A08, reg_ephy_base + 0x4c);
|
||||
writel(0x244C, reg_ephy_base + 0x50);
|
||||
writel(0x1A44, reg_ephy_base + 0x54);
|
||||
writel(0x061C, reg_ephy_base + 0x58);
|
||||
|
||||
// Switch to MII-page14
|
||||
writel(0x0e00, reg_ephy_base + 0x7c);
|
||||
|
||||
writel(0x2D30, reg_ephy_base + 0x40);
|
||||
writel(0x3470, reg_ephy_base + 0x44);
|
||||
writel(0x0648, reg_ephy_base + 0x48);
|
||||
writel(0x261C, reg_ephy_base + 0x4c);
|
||||
writel(0x3160, reg_ephy_base + 0x50);
|
||||
writel(0x2D5E, reg_ephy_base + 0x54);
|
||||
|
||||
// Switch to MII-page15
|
||||
writel(0x0f00, reg_ephy_base + 0x7c);
|
||||
|
||||
writel(0x2922, reg_ephy_base + 0x40);
|
||||
writel(0x366E, reg_ephy_base + 0x44);
|
||||
writel(0x0752, reg_ephy_base + 0x48);
|
||||
writel(0x2556, reg_ephy_base + 0x4c);
|
||||
writel(0x2348, reg_ephy_base + 0x50);
|
||||
writel(0x0C30, reg_ephy_base + 0x54);
|
||||
|
||||
// Switch to MII-page16
|
||||
writel(0x1000, reg_ephy_base + 0x7c);
|
||||
|
||||
writel(0x1E08, reg_ephy_base + 0x40);
|
||||
writel(0x3868, reg_ephy_base + 0x44);
|
||||
writel(0x1462, reg_ephy_base + 0x48);
|
||||
writel(0x1A0E, reg_ephy_base + 0x4c);
|
||||
writel(0x305E, reg_ephy_base + 0x50);
|
||||
writel(0x2F62, reg_ephy_base + 0x54);
|
||||
|
||||
// LED
|
||||
// Switch to MII-page1
|
||||
writel(0x0100, reg_ephy_base + 0x7c);
|
||||
|
||||
// select LED_LNK/SPD/DPX out to LED_PAD
|
||||
writel((readl(reg_ephy_base + 0x68) & ~0x0f00), reg_ephy_base + 0x68);
|
||||
|
||||
// Switch to MII-page19
|
||||
writel(0x1300, reg_ephy_base + 0x7c);
|
||||
writel(0x0012, reg_ephy_base + 0x58);
|
||||
// set agc max/min swing
|
||||
writel(0x6848, reg_ephy_base + 0x5c);
|
||||
|
||||
// Switch to MII-page18
|
||||
writel(0x1200, reg_ephy_base + 0x7c);
|
||||
#if IS_ENABLED(CONFIG_ARCH_CV181X)
|
||||
/* mars LPF(8, 8, 8, 8) HPF(-8, 50(+32), -36, -8) */
|
||||
// lpf
|
||||
writel(0x0808, reg_ephy_base + 0x48);
|
||||
writel(0x0808, reg_ephy_base + 0x4c);
|
||||
// hpf
|
||||
writel(0x32f8, reg_ephy_base + 0x50);
|
||||
writel(0xf8dc, reg_ephy_base + 0x54);
|
||||
#elif IS_ENABLED(CONFIG_ARCH_CV180X)
|
||||
/* phobos LPF:(1 8 23 23 8 1) HPF:(-4,58,-45,8,-5, 0) from sean PPT */
|
||||
// lpf
|
||||
writel(0x0801, reg_ephy_base + 0x48);
|
||||
writel(0x1717, reg_ephy_base + 0x4C);
|
||||
writel(0x0108, reg_ephy_base + 0x5C);
|
||||
// hpf
|
||||
writel(0x3afc, reg_ephy_base + 0x50);
|
||||
writel(0x08d3, reg_ephy_base + 0x54);
|
||||
writel(0x00fb, reg_ephy_base + 0x60);
|
||||
#endif
|
||||
|
||||
// Switch to MII-page0
|
||||
writel(0x0000, reg_ephy_base + 0x7c);
|
||||
// EPHY start auto-neg procedure
|
||||
writel(0x090e, reg_ephy_top_wrap);
|
||||
|
||||
// from jinyu.zhao
|
||||
/* EPHY is configured as half-duplex after reset, but we need force full-duplex */
|
||||
writel((readl(reg_ephy_base) | 0x100), reg_ephy_base);
|
||||
|
||||
// switch to MDIO control by ETH_MAC
|
||||
writel(0x0000, reg_ephy_top_wrap + 4);
|
||||
|
||||
iounmap(reg_ephy_base);
|
||||
err_ephy_mem_2:
|
||||
iounmap(reg_ephy_top_wrap);
|
||||
err_ephy_mem_1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct phy_driver cvitek_phy_driver[] = {
|
||||
static struct phy_driver cv182xa_phy_driver[] = {
|
||||
{
|
||||
.phy_id = 0x00441400,
|
||||
.phy_id_mask = 0xfffffff0,
|
||||
.name = "CVITEK CVI18XX",
|
||||
.get_features = genphy_read_abilities,
|
||||
.read_status = cvi_read_status,
|
||||
.phy_id = 0x00435649,
|
||||
.phy_id_mask = 0xffffffff,
|
||||
.name = "CVITEK CV182XA",
|
||||
.config_init = cv182xa_phy_config_init,
|
||||
.config_aneg = cv182xa_phy_config_aneg,
|
||||
.read_status = cv182xa_read_status,
|
||||
/* IRQ related */
|
||||
.ack_interrupt = cvi_phy_ack_interrupt,
|
||||
.config_intr = cvi_phy_config_intr,
|
||||
.ack_interrupt = cv182xa_phy_ack_interrupt,
|
||||
.config_intr = cv182xa_phy_config_intr,
|
||||
.aneg_done = genphy_aneg_done,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = genphy_resume,
|
||||
.set_loopback = genphy_loopback,
|
||||
} };
|
||||
|
||||
module_phy_driver(cvitek_phy_driver);
|
||||
module_phy_driver(cv182xa_phy_driver);
|
||||
|
||||
MODULE_DESCRIPTION("CVITEK PHY driver");
|
||||
MODULE_DESCRIPTION("CV182XA EPHY driver");
|
||||
MODULE_AUTHOR("Ethan Chen");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static struct mdio_device_id __maybe_unused cvitek_tbl[] = {
|
||||
{ 0x00441400, 0xfffffff0 },
|
||||
static struct mdio_device_id __maybe_unused cv182xa_tbl[] = {
|
||||
{ 0x00435649, 0xffffffff },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(mdio, cvitek_tbl);
|
||||
MODULE_DEVICE_TABLE(mdio, cv182xa_tbl);
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/memblock.h>
|
||||
|
||||
#define MAX_RESERVED_REGIONS 64
|
||||
#define MAX_RESERVED_REGIONS 4
|
||||
|
||||
#if defined(CONFIG_ARCH_CVITEK)
|
||||
struct reserved_mem_size_entry {
|
||||
@ -69,7 +69,7 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
|
||||
}
|
||||
|
||||
rmem->fdt_node = node;
|
||||
rmem->name = uname;
|
||||
strncpy(rmem->name, uname, 8);
|
||||
rmem->base = base;
|
||||
rmem->size = size;
|
||||
|
||||
|
||||
11
linux_5.10/include/linux/cv180x_efuse.h
Normal file
11
linux_5.10/include/linux/cv180x_efuse.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __CVI_EFUSE_H__
|
||||
#define __CVI_EFUSE_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
int64_t cvi_efuse_read_from_shadow(uint32_t addr);
|
||||
int cvi_efuse_write(uint32_t addr, uint32_t value);
|
||||
|
||||
int cvi_efuse_read_buf(u32 addr, void *buf, size_t buf_size);
|
||||
|
||||
#endif /* __CVI_EFUSE_H__ */
|
||||
@ -9,7 +9,7 @@ struct of_phandle_args;
|
||||
struct reserved_mem_ops;
|
||||
|
||||
struct reserved_mem {
|
||||
const char *name;
|
||||
char name[8];
|
||||
unsigned long fdt_node;
|
||||
unsigned long phandle;
|
||||
const struct reserved_mem_ops *ops;
|
||||
|
||||
@ -1 +0,0 @@
|
||||
../../../../build/output/cv1800b_wdmb_0008a_spinor/cvi_board_memmap.h
|
||||
@ -30,14 +30,32 @@ static int cv1835_pdm_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||
static struct snd_soc_ops cv1835_pdm_ops = {
|
||||
.hw_params = cv1835_pdm_hw_params,
|
||||
};
|
||||
static struct snd_soc_dai_link_component cv1835_pdm_cpus = {
|
||||
.name = "4110000.i2s",
|
||||
.dai_name = "4110000.i2s",
|
||||
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link_component cv1835_pdm_codecs = {
|
||||
.name = "41d0c00.pdm",
|
||||
.dai_name = "cv1835pdm",
|
||||
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link_component cv1835_pdm_platform = {
|
||||
.name = "4110000.i2s",
|
||||
.dai_name = "4110000.i2s",
|
||||
|
||||
};
|
||||
static struct snd_soc_dai_link cv1835_pdm_dai = {
|
||||
.name = "cv1835-i2s-1",
|
||||
.stream_name = "cv1835-pdm",
|
||||
.cpu_dai_name = "4110000.i2s",
|
||||
.codec_dai_name = "cv1835pdm",
|
||||
.platform_name = "4110000.i2s",
|
||||
.codec_name = "41d0c00.pdm",
|
||||
.cpus = &cv1835_pdm_cpus,
|
||||
.num_cpus = 1,
|
||||
.codecs = &cv1835_pdm_codecs,
|
||||
.num_codecs = 1,
|
||||
.platforms = &cv1835_pdm_platform,
|
||||
.num_platforms = 1,
|
||||
.ops = &cv1835_pdm_ops,
|
||||
.init = cv1835_pdm_codec_init,
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S
|
||||
@ -56,7 +74,7 @@ static struct snd_soc_card cv1835_pdm = {
|
||||
|
||||
static const struct of_device_id cvi_audio_match_ids[] = {
|
||||
{
|
||||
.compatible = "cvitek,cv1835-pdm",
|
||||
.compatible = "cvitek,cv182x-pdm",
|
||||
//.data = (void *) &cv1835_pdm_dai,
|
||||
},
|
||||
{ }
|
||||
|
||||
@ -223,6 +223,8 @@ static int cv1835pdm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct cvi1835pdm *pdm;
|
||||
struct resource *res;
|
||||
struct miscdevice *miscdev;
|
||||
int ret;
|
||||
|
||||
dev_info(&pdev->dev, "%s\n", __func__);
|
||||
|
||||
@ -236,6 +238,17 @@ static int cv1835pdm_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(pdm->pdm_base))
|
||||
return PTR_ERR(pdm->pdm_base);
|
||||
|
||||
miscdev = &pdm->miscdev;
|
||||
miscdev->minor = MISC_DYNAMIC_MINOR;
|
||||
miscdev->name = "cv1835pdm";
|
||||
//miscdev->fops = &adc_fops;
|
||||
miscdev->parent = NULL;
|
||||
|
||||
ret = misc_register(miscdev);
|
||||
if (ret) {
|
||||
pr_err("pdm: failed to register misc device.\n");
|
||||
return ret;
|
||||
}
|
||||
dev_set_drvdata(&pdev->dev, pdm);
|
||||
pdm->dev = &pdev->dev;
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
#define __CV1835PDM_H__
|
||||
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <linux/miscdevice.h>
|
||||
/* register offset */
|
||||
#define PDM_EN_REG 0x30
|
||||
#define PDM_EN 0x1
|
||||
@ -56,6 +56,7 @@ struct cvi1835pdm {
|
||||
void __iomem *pdm_base;
|
||||
struct clk *clk;
|
||||
struct device *dev;
|
||||
struct miscdevice miscdev;
|
||||
};
|
||||
|
||||
#endif /* __CV1835PDM_H__ */
|
||||
|
||||
Reference in New Issue
Block a user