diff --git a/linux_5.10/.gitignore b/linux_5.10/.gitignore new file mode 100644 index 000000000..b8e058094 --- /dev/null +++ b/linux_5.10/.gitignore @@ -0,0 +1,2 @@ +build/ +scripts/dtc/include-prefixes/cvi_board_memmap.h diff --git a/linux_5.10/arch/arm64/Kconfig.platforms b/linux_5.10/arch/arm64/Kconfig.platforms index 3ae0cd6cf..25f1e2883 100644 --- a/linux_5.10/arch/arm64/Kconfig.platforms +++ b/linux_5.10/arch/arm64/Kconfig.platforms @@ -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" diff --git a/linux_5.10/drivers/Kconfig b/linux_5.10/drivers/Kconfig index dcecc9f6e..70c2b2df4 100644 --- a/linux_5.10/drivers/Kconfig +++ b/linux_5.10/drivers/Kconfig @@ -235,4 +235,6 @@ source "drivers/interconnect/Kconfig" source "drivers/counter/Kconfig" source "drivers/most/Kconfig" + +source "drivers/efuse/Kconfig" endmenu diff --git a/linux_5.10/drivers/Makefile b/linux_5.10/drivers/Makefile index 576228037..8e9c3be86 100644 --- a/linux_5.10/drivers/Makefile +++ b/linux_5.10/drivers/Makefile @@ -189,3 +189,4 @@ obj-$(CONFIG_GNSS) += gnss/ obj-$(CONFIG_INTERCONNECT) += interconnect/ obj-$(CONFIG_COUNTER) += counter/ obj-$(CONFIG_MOST) += most/ +obj-$(CONFIG_EFUSE) += efuse/ diff --git a/linux_5.10/drivers/efuse/Kconfig b/linux_5.10/drivers/efuse/Kconfig new file mode 100644 index 000000000..c16c8576a --- /dev/null +++ b/linux_5.10/drivers/efuse/Kconfig @@ -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 diff --git a/linux_5.10/drivers/efuse/Makefile b/linux_5.10/drivers/efuse/Makefile new file mode 100644 index 000000000..e62984a80 --- /dev/null +++ b/linux_5.10/drivers/efuse/Makefile @@ -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 + diff --git a/linux_5.10/drivers/efuse/cv180x_efuse.c b/linux_5.10/drivers/efuse/cv180x_efuse.c new file mode 100644 index 000000000..fa07112c3 --- /dev/null +++ b/linux_5.10/drivers/efuse/cv180x_efuse.c @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// EFUSE implementation +// + +#include +#include +#include +#include +#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"); diff --git a/linux_5.10/drivers/efuse/cv181x_efuse.c b/linux_5.10/drivers/efuse/cv181x_efuse.c new file mode 100644 index 000000000..979a13c25 --- /dev/null +++ b/linux_5.10/drivers/efuse/cv181x_efuse.c @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// EFUSE implementation +// + +#include +#include +#include +#include + +#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"); diff --git a/linux_5.10/drivers/mtd/spi-nor/cvitek_support_list.c b/linux_5.10/drivers/mtd/spi-nor/cvitek_support_list.c index a455d93c2..2dc7454af 100644 --- a/linux_5.10/drivers/mtd/spi-nor/cvitek_support_list.c +++ b/linux_5.10/drivers/mtd/spi-nor/cvitek_support_list.c @@ -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 }, diff --git a/linux_5.10/drivers/net/phy/Kconfig b/linux_5.10/drivers/net/phy/Kconfig index e76b17be3..3d1fa2782 100644 --- a/linux_5.10/drivers/net/phy/Kconfig +++ b/linux_5.10/drivers/net/phy/Kconfig @@ -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. diff --git a/linux_5.10/drivers/net/phy/Makefile b/linux_5.10/drivers/net/phy/Makefile index db95bc2e0..a9102835b 100644 --- a/linux_5.10/drivers/net/phy/Makefile +++ b/linux_5.10/drivers/net/phy/Makefile @@ -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 diff --git a/linux_5.10/drivers/net/phy/cvitek.c b/linux_5.10/drivers/net/phy/cvitek.c index 89a5c23a8..555eb01fb 100644 --- a/linux_5.10/drivers/net/phy/cvitek.c +++ b/linux_5.10/drivers/net/phy/cvitek.c @@ -8,136 +8,53 @@ #include #include #include +#include +#include -#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); diff --git a/linux_5.10/drivers/of/of_reserved_mem.c b/linux_5.10/drivers/of/of_reserved_mem.c index b5fcdcae5..29750d724 100644 --- a/linux_5.10/drivers/of/of_reserved_mem.c +++ b/linux_5.10/drivers/of/of_reserved_mem.c @@ -22,7 +22,7 @@ #include #include -#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; diff --git a/linux_5.10/include/linux/cv180x_efuse.h b/linux_5.10/include/linux/cv180x_efuse.h new file mode 100644 index 000000000..e9c46fbe8 --- /dev/null +++ b/linux_5.10/include/linux/cv180x_efuse.h @@ -0,0 +1,11 @@ +#ifndef __CVI_EFUSE_H__ +#define __CVI_EFUSE_H__ + +#include + +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__ */ diff --git a/linux_5.10/include/linux/of_reserved_mem.h b/linux_5.10/include/linux/of_reserved_mem.h index 8216a4156..e418313a5 100644 --- a/linux_5.10/include/linux/of_reserved_mem.h +++ b/linux_5.10/include/linux/of_reserved_mem.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; diff --git a/linux_5.10/scripts/dtc/include-prefixes/cvi_board_memmap.h b/linux_5.10/scripts/dtc/include-prefixes/cvi_board_memmap.h deleted file mode 120000 index bb6306658..000000000 --- a/linux_5.10/scripts/dtc/include-prefixes/cvi_board_memmap.h +++ /dev/null @@ -1 +0,0 @@ -../../../../build/output/cv1800b_wdmb_0008a_spinor/cvi_board_memmap.h \ No newline at end of file diff --git a/linux_5.10/sound/soc/cvitek/cv1835_cv1835pdm.c b/linux_5.10/sound/soc/cvitek/cv1835_cv1835pdm.c index dec0d6bb9..517269636 100644 --- a/linux_5.10/sound/soc/cvitek/cv1835_cv1835pdm.c +++ b/linux_5.10/sound/soc/cvitek/cv1835_cv1835pdm.c @@ -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, }, { } diff --git a/linux_5.10/sound/soc/cvitek/cv1835pdm.c b/linux_5.10/sound/soc/cvitek/cv1835pdm.c index 3f7a55438..2e06aba47 100644 --- a/linux_5.10/sound/soc/cvitek/cv1835pdm.c +++ b/linux_5.10/sound/soc/cvitek/cv1835pdm.c @@ -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; diff --git a/linux_5.10/sound/soc/cvitek/cv1835pdm.h b/linux_5.10/sound/soc/cvitek/cv1835pdm.h index 81b3ed10a..4ac9a9c09 100644 --- a/linux_5.10/sound/soc/cvitek/cv1835pdm.h +++ b/linux_5.10/sound/soc/cvitek/cv1835pdm.h @@ -11,7 +11,7 @@ #define __CV1835PDM_H__ #include - +#include /* 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__ */