Commit 95dcbe56 authored by wangliang.wang's avatar wangliang.wang Committed by sam.xiang

[linux] Upgrade the MMF SDK from V4.0.0 to V4.1.0

	1. 181x support secureboot
	2. add .gitignore

Change-Id: I34cd45663d92eeb8e3b5ddfbf1a876111ce46bd1
parent 221f3d93
build/
scripts/dtc/include-prefixes/cvi_board_memmap.h
...@@ -370,6 +370,16 @@ config ARCH_CV181X ...@@ -370,6 +370,16 @@ config ARCH_CV181X
help help
This enables support for Cvitek's CV181X 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 config ARCH_CV952X
bool "Cvitek CV952X SoC" bool "Cvitek CV952X SoC"
select PINCTRL select PINCTRL
...@@ -476,6 +486,39 @@ config ARCH_CV181X_ASIC ...@@ -476,6 +486,39 @@ config ARCH_CV181X_ASIC
endchoice endchoice
endif # end ARCH_CV181X 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 if ARCH_CV952X
config ARCH_CVITEK_CHIP config ARCH_CVITEK_CHIP
string "cv952x" string "cv952x"
......
...@@ -235,4 +235,6 @@ source "drivers/interconnect/Kconfig" ...@@ -235,4 +235,6 @@ source "drivers/interconnect/Kconfig"
source "drivers/counter/Kconfig" source "drivers/counter/Kconfig"
source "drivers/most/Kconfig" source "drivers/most/Kconfig"
source "drivers/efuse/Kconfig"
endmenu endmenu
...@@ -189,3 +189,4 @@ obj-$(CONFIG_GNSS) += gnss/ ...@@ -189,3 +189,4 @@ obj-$(CONFIG_GNSS) += gnss/
obj-$(CONFIG_INTERCONNECT) += interconnect/ obj-$(CONFIG_INTERCONNECT) += interconnect/
obj-$(CONFIG_COUNTER) += counter/ obj-$(CONFIG_COUNTER) += counter/
obj-$(CONFIG_MOST) += most/ obj-$(CONFIG_MOST) += most/
obj-$(CONFIG_EFUSE) += efuse/
# 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
# 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
// 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");
// 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[] = { ...@@ -157,6 +157,12 @@ static const struct flash_info cvitek_parts[] = {
{ "FM25Q64", INFO(0xF83217, 0x0, 64 * 1024, 128, { "FM25Q64", INFO(0xF83217, 0x0, 64 * 1024, 128,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_OP) SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_OP)
.fixups = &sr_bit1_qe_fixups }, .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, { "BY25Q128AS", INFO(0x684018, 0x0, 64 * 1024, 256,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_OP) SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_OP)
.fixups = &sr_bit1_qe_fixups }, .fixups = &sr_bit1_qe_fixups },
......
...@@ -158,11 +158,11 @@ config CICADA_PHY ...@@ -158,11 +158,11 @@ config CICADA_PHY
help help
Currently supports the cis8204 Currently supports the cis8204
config CV182XA_PHY config CVITEK_PHY
tristate "CV182XA PHYs" tristate "CVITEK PHYs"
help help
Enable support for RMII PHYs manufactured by CVITEK Enable support for RMII PHYs manufactured by CVITEK
Include driver for cv182xa. Include driver for cvitek.
This is an internal ethernet phy. This is an internal ethernet phy.
And support 100Mbs full duplex. And support 100Mbs full duplex.
......
...@@ -48,7 +48,6 @@ obj-$(CONFIG_BCM_CYGNUS_PHY) += bcm-cygnus.o ...@@ -48,7 +48,6 @@ obj-$(CONFIG_BCM_CYGNUS_PHY) += bcm-cygnus.o
obj-$(CONFIG_BCM_NET_PHYLIB) += bcm-phy-lib.o obj-$(CONFIG_BCM_NET_PHYLIB) += bcm-phy-lib.o
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
obj-$(CONFIG_CICADA_PHY) += cicada.o obj-$(CONFIG_CICADA_PHY) += cicada.o
obj-$(CONFIG_CV182XA_PHY) += cv182xa.o
obj-$(CONFIG_CVITEK_PHY) += cvitek.o obj-$(CONFIG_CVITEK_PHY) += cvitek.o
obj-$(CONFIG_CORTINA_PHY) += cortina.o obj-$(CONFIG_CORTINA_PHY) += cortina.o
obj-$(CONFIG_DAVICOM_PHY) += davicom.o obj-$(CONFIG_DAVICOM_PHY) += davicom.o
......
...@@ -8,136 +8,53 @@ ...@@ -8,136 +8,53 @@
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/io.h>
#include <linux/cv180x_efuse.h>
#define CVI_ETH_PHY_ADC_CTRL 16 #define REG_EPHY_TOP_WRAP 0x03009800
#define CVI_ETH_PHY_INT_STS 16 #define REG_EPHY_BASE 0x03009000
#define CVI_ETH_AUTO_CALIBRATE 16 #define EPHY_EFUSE_TXECHORC_FLAG 0x00000100 // bit 8
#define CVI_ETH_PHY_INT_MASK 17 #define EPHY_EFUSE_TXITUNE_FLAG 0x00000200 // bit 9
#define CVI_ETH_PHY_APS 18 #define EPHY_EFUSE_TXRXTERM_FLAG 0x00000800 // bit 11
#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 CVI_INT_EVENTS \ #define CVI_INT_EVENTS \
(CVI_LNK_STS_CHG_INT_MSK | CVI_MGC_PKT_DET_INT_MSK) (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, return 0;
((phydev->interrupts == PHY_INTERRUPT_ENABLED)
? CVI_INT_EVENTS
: 0));
return rc < 0 ? rc : 0;
} }
static int cvi_phy_ack_interrupt(struct phy_device *phydev) static int cv182xa_phy_ack_interrupt(struct phy_device *phydev)
{ {
int err; return 0;
pr_debug("%s, clear interrupts\n", __func__);
err = phy_write(phydev, CVI_ETH_PHY_INT_STS, 0xf000);
return err < 0 ? err : 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); int err = genphy_read_status(phydev);
pr_debug("%s, speed=%d, duplex=%d, ", __func__, phydev->speed, phydev->duplex); 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("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; return err;
} }
#if defined(CONFIG_CVITEK_PHY_UAPS) #if defined(CONFIG_CVITEK_PHY_UAPS)
/* Ultra Auto Power Saving mode */ /* 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; return 0;
} }
#endif #endif
static int cvi_phy_config_aneg(struct phy_device *phydev) static int cv182xa_phy_config_aneg(struct phy_device *phydev)
{ {
int ret; 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) #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 #endif
/* switch back to page 0 */
phy_write(phydev, CVI_ETH_PHY_PAGE_SEL, CVI_ETH_PHY_PAGE_0);
ret = genphy_config_aneg(phydev); ret = genphy_config_aneg(phydev);
...@@ -147,42 +64,310 @@ static int cvi_phy_config_aneg(struct phy_device *phydev) ...@@ -147,42 +64,310 @@ static int cvi_phy_config_aneg(struct phy_device *phydev)
return 0; 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;
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;
}
// 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
ret = genphy_read_abilities(phydev); // Switch to MII-page0
if (ret < 0) writel(0x0000, reg_ephy_base + 0x7c);
return ret; // EPHY start auto-neg procedure
writel(0x090e, reg_ephy_top_wrap);
return 0; // 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 = 0x00435649,
.phy_id_mask = 0xfffffff0, .phy_id_mask = 0xffffffff,
.name = "CVITEK CVI18XX", .name = "CVITEK CV182XA",
.get_features = genphy_read_abilities, .config_init = cv182xa_phy_config_init,
.read_status = cvi_read_status, .config_aneg = cv182xa_phy_config_aneg,
.read_status = cv182xa_read_status,
/* IRQ related */ /* IRQ related */
.ack_interrupt = cvi_phy_ack_interrupt, .ack_interrupt = cv182xa_phy_ack_interrupt,
.config_intr = cvi_phy_config_intr, .config_intr = cv182xa_phy_config_intr,
.aneg_done = genphy_aneg_done, .aneg_done = genphy_aneg_done,
.suspend = genphy_suspend, .suspend = genphy_suspend,
.resume = genphy_resume, .resume = genphy_resume,
.set_loopback = genphy_loopback, .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_AUTHOR("Ethan Chen");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static struct mdio_device_id __maybe_unused cvitek_tbl[] = { static struct mdio_device_id __maybe_unused cv182xa_tbl[] = {
{ 0x00441400, 0xfffffff0 }, { 0x00435649, 0xffffffff },
{ } { }
}; };
MODULE_DEVICE_TABLE(mdio, cvitek_tbl); MODULE_DEVICE_TABLE(mdio, cv182xa_tbl);
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#define MAX_RESERVED_REGIONS 64 #define MAX_RESERVED_REGIONS 4
#if defined(CONFIG_ARCH_CVITEK) #if defined(CONFIG_ARCH_CVITEK)
struct reserved_mem_size_entry { struct reserved_mem_size_entry {
...@@ -69,7 +69,7 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, ...@@ -69,7 +69,7 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
} }
rmem->fdt_node = node; rmem->fdt_node = node;
rmem->name = uname; strncpy(rmem->name, uname, 8);
rmem->base = base; rmem->base = base;
rmem->size = size; rmem->size = size;
......
#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; ...@@ -9,7 +9,7 @@ struct of_phandle_args;
struct reserved_mem_ops; struct reserved_mem_ops;
struct reserved_mem { struct reserved_mem {
const char *name; char name[8];
unsigned long fdt_node; unsigned long fdt_node;
unsigned long phandle; unsigned long phandle;
const struct reserved_mem_ops *ops; const struct reserved_mem_ops *ops;
......
../../../../build/output/cv1800b_wdmb_0008a_spinor/cvi_board_memmap.h
\ No newline at end of file
...@@ -30,14 +30,32 @@ static int cv1835_pdm_codec_init(struct snd_soc_pcm_runtime *rtd) ...@@ -30,14 +30,32 @@ static int cv1835_pdm_codec_init(struct snd_soc_pcm_runtime *rtd)
static struct snd_soc_ops cv1835_pdm_ops = { static struct snd_soc_ops cv1835_pdm_ops = {
.hw_params = cv1835_pdm_hw_params, .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 = { static struct snd_soc_dai_link cv1835_pdm_dai = {
.name = "cv1835-i2s-1", .name = "cv1835-i2s-1",
.stream_name = "cv1835-pdm", .stream_name = "cv1835-pdm",
.cpu_dai_name = "4110000.i2s", .cpus = &cv1835_pdm_cpus,
.codec_dai_name = "cv1835pdm", .num_cpus = 1,
.platform_name = "4110000.i2s", .codecs = &cv1835_pdm_codecs,
.codec_name = "41d0c00.pdm", .num_codecs = 1,
.platforms = &cv1835_pdm_platform,
.num_platforms = 1,
.ops = &cv1835_pdm_ops, .ops = &cv1835_pdm_ops,
.init = cv1835_pdm_codec_init, .init = cv1835_pdm_codec_init,
.dai_fmt = SND_SOC_DAIFMT_I2S .dai_fmt = SND_SOC_DAIFMT_I2S
...@@ -56,7 +74,7 @@ static struct snd_soc_card cv1835_pdm = { ...@@ -56,7 +74,7 @@ static struct snd_soc_card cv1835_pdm = {
static const struct of_device_id cvi_audio_match_ids[] = { static const struct of_device_id cvi_audio_match_ids[] = {
{ {
.compatible = "cvitek,cv1835-pdm", .compatible = "cvitek,cv182x-pdm",
//.data = (void *) &cv1835_pdm_dai, //.data = (void *) &cv1835_pdm_dai,
}, },
{ } { }
......
...@@ -223,6 +223,8 @@ static int cv1835pdm_probe(struct platform_device *pdev) ...@@ -223,6 +223,8 @@ static int cv1835pdm_probe(struct platform_device *pdev)
{ {
struct cvi1835pdm *pdm; struct cvi1835pdm *pdm;
struct resource *res; struct resource *res;
struct miscdevice *miscdev;
int ret;
dev_info(&pdev->dev, "%s\n", __func__); dev_info(&pdev->dev, "%s\n", __func__);
...@@ -236,6 +238,17 @@ static int cv1835pdm_probe(struct platform_device *pdev) ...@@ -236,6 +238,17 @@ static int cv1835pdm_probe(struct platform_device *pdev)
if (IS_ERR(pdm->pdm_base)) if (IS_ERR(pdm->pdm_base))
return PTR_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); dev_set_drvdata(&pdev->dev, pdm);
pdm->dev = &pdev->dev; pdm->dev = &pdev->dev;
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#define __CV1835PDM_H__ #define __CV1835PDM_H__
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/miscdevice.h>
/* register offset */ /* register offset */
#define PDM_EN_REG 0x30 #define PDM_EN_REG 0x30
#define PDM_EN 0x1 #define PDM_EN 0x1
...@@ -56,6 +56,7 @@ struct cvi1835pdm { ...@@ -56,6 +56,7 @@ struct cvi1835pdm {
void __iomem *pdm_base; void __iomem *pdm_base;
struct clk *clk; struct clk *clk;
struct device *dev; struct device *dev;
struct miscdevice miscdev;
}; };
#endif /* __CV1835PDM_H__ */ #endif /* __CV1835PDM_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment