Merge commit '0f7094037eff3940d4b6f6b1743a7d4a5a5e2b21'

* commit '0f7094037eff3940d4b6f6b1743a7d4a5a5e2b21':
  PCI: rockchip: dw: Remove forward definition of rk_pcie_{enable, disable}_power
  PCI: rockchip: dw: Reorder and document steps of rk_pcie_really_probe()
  PCI: rockchip: dw: Move debugfs all into rockchip_pcie_debugfs_init()
  PCI: rockchip: dw: Move dma_obj initialization into rk_pcie_init_dma_trx()
  PCI: rockchip: dw: Move irq and wq into rk_pcie_init_irq_and_wq()
  PCI: rockchip: dw: Release PCIe reset/clock before phy initial
  PCI: rockchip: dw: Move getting lpbk and comp into rk_pcie_resource_get()
  PCI: rockchip: dw: Move getting skip_scan_in_resume into rk_pcie_resource_get()
  PCI: rockchip: dw: Move getting vpcie3v3 into rk_pcie_resource_get()
  PCI: rockchip: dw: Move getting clkreq, HP and bifurcation into rk_pcie_resource_get()
  PCI: rockchip: dw: Move getting rsts into rk_pcie_resource_get()
  PCI: rockchip: dw: Remove rk_pcie_clk_init()
  ASoC: rockchip: multicodecs: add tdm support
  exfat: fix memory leak in exfat_load_bitmap()
  ARM: rk3506_defconfig: Disable CONFIG_ROCKCHIP_CLK_INV/PVTM/CONFIG_ROCKCHIP_PVTM
  media: rockchip: flexbus_cif: Add MODULE_IMPORT_NS(DMA_BUF)

Change-Id: I3dbd56660ca2a8773cabda0675eaa25578ffabc0
This commit is contained in:
Tao Huang
2024-08-27 19:54:49 +08:00
5 changed files with 418 additions and 372 deletions

View File

@@ -282,13 +282,14 @@ CONFIG_DMABUF_HEAPS_CMA=y
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
CONFIG_STAGING=y
# CONFIG_ROCKCHIP_CLK_INV is not set
CONFIG_ROCKCHIP_CLK_OUT=y
# CONFIG_ROCKCHIP_CLK_PVTM is not set
# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_CPU_RK3506=y
CONFIG_ROCKCHIP_CPUINFO=y
CONFIG_ROCKCHIP_OPP=y
CONFIG_ROCKCHIP_PVTM=y
CONFIG_ROCKCHIP_SUSPEND_MODE=y
CONFIG_ROCKCHIP_SYSTEM_MONITOR=y
CONFIG_FIQ_DEBUGGER=y

View File

@@ -11,6 +11,8 @@
#include "dev.h"
#include "common.h"
MODULE_IMPORT_NS(DMA_BUF);
static void flexbus_cif_init_dummy_vb2(struct flexbus_cif_device *dev,
struct flexbus_cif_dummy_buffer *buf)
{

View File

@@ -135,6 +135,9 @@ struct rk_pcie {
bool slot_pluggable;
struct gpio_hotplug_slot hp_slot;
bool hp_no_link;
bool is_lpbk;
bool is_comp;
bool have_rasdes;
struct regulator *vpcie3v3;
struct irq_domain *irq_domain;
raw_spinlock_t intx_lock;
@@ -153,8 +156,6 @@ struct rk_pcie_of_data {
};
#define to_rk_pcie(x) dev_get_drvdata((x)->dev)
static int rk_pcie_disable_power(struct rk_pcie *rk_pcie);
static int rk_pcie_enable_power(struct rk_pcie *rk_pcie);
static inline u32 rk_pcie_readl_apb(struct rk_pcie *rk_pcie, u32 reg)
{
@@ -201,7 +202,7 @@ static void disable_aspm_l1ss(struct rk_pcie *rk_pcie)
static inline void disable_aspm_l1ss(struct rk_pcie *rk_pcie) { return; }
#endif
static inline void rk_pcie_set_mode(struct rk_pcie *rk_pcie)
static inline void rk_pcie_set_rc_mode(struct rk_pcie *rk_pcie)
{
if (rk_pcie->supports_clkreq) {
/* Application is ready to have reference clock removed */
@@ -272,6 +273,36 @@ static void rk_pcie_debug_dump(struct rk_pcie *rk_pcie)
#endif
}
static int rk_pcie_enable_power(struct rk_pcie *rk_pcie)
{
int ret = 0;
struct device *dev = rk_pcie->pci->dev;
if (IS_ERR(rk_pcie->vpcie3v3))
return ret;
ret = regulator_enable(rk_pcie->vpcie3v3);
if (ret)
dev_err(dev, "fail to enable vpcie3v3 regulator\n");
return ret;
}
static int rk_pcie_disable_power(struct rk_pcie *rk_pcie)
{
int ret = 0;
struct device *dev = rk_pcie->pci->dev;
if (IS_ERR(rk_pcie->vpcie3v3))
return ret;
ret = regulator_disable(rk_pcie->vpcie3v3);
if (ret)
dev_err(dev, "fail to disable vpcie3v3 regulator\n");
return ret;
}
static int rk_pcie_establish_link(struct dw_pcie *pci)
{
int retries, power;
@@ -392,182 +423,6 @@ static bool rk_pcie_udma_enabled(struct rk_pcie *rk_pcie)
PCIE_DMA_CTRL_OFF);
}
static int rk_pcie_init_dma_trx(struct rk_pcie *rk_pcie)
{
if (!rk_pcie_udma_enabled(rk_pcie))
return 0;
rk_pcie->dma_obj = pcie_dw_dmatest_register(rk_pcie->pci->dev, true);
if (IS_ERR(rk_pcie->dma_obj)) {
dev_err(rk_pcie->pci->dev, "failed to prepare dmatest\n");
return -EINVAL;
}
/* Enable client write and read interrupt */
rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0xc000000);
/* Enable core write interrupt */
dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_MASK,
0x0);
/* Enable core read interrupt */
dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_MASK,
0x0);
return 0;
}
#ifdef MODULE
void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, size_t size, u32 val)
{
int ret;
if (pci->ops && pci->ops->write_dbi2) {
pci->ops->write_dbi2(pci, pci->dbi_base2, reg, size, val);
return;
}
ret = dw_pcie_write(pci->dbi_base2 + reg, size, val);
if (ret)
dev_err(pci->dev, "write DBI address failed\n");
}
#endif
static struct dw_pcie_host_ops rk_pcie_host_ops;
static int rk_add_pcie_port(struct rk_pcie *rk_pcie, struct platform_device *pdev)
{
int ret;
struct dw_pcie *pci = rk_pcie->pci;
struct dw_pcie_rp *pp = &pci->pp;
struct device *dev = pci->dev;
pp->ops = &rk_pcie_host_ops;
if (IS_ENABLED(CONFIG_PCI_MSI)) {
if (rk_pcie->msi_vector_num > 0) {
dev_info(dev, "max MSI vector is %d\n", rk_pcie->msi_vector_num);
pp->num_vectors = rk_pcie->msi_vector_num;
}
}
ret = dw_pcie_host_init(pp);
if (ret) {
dev_err(dev, "failed to initialize host\n");
return ret;
}
/* Disable BAR0 BAR1 */
dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_0, 0x0);
dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_1, 0x0);
return 0;
}
static int rk_pcie_clk_init(struct rk_pcie *rk_pcie)
{
struct device *dev = rk_pcie->pci->dev;
int ret;
rk_pcie->clk_cnt = devm_clk_bulk_get_all(dev, &rk_pcie->clks);
if (rk_pcie->clk_cnt < 1)
return -ENODEV;
ret = clk_bulk_prepare_enable(rk_pcie->clk_cnt, rk_pcie->clks);
if (ret) {
dev_err(dev, "failed to prepare enable pcie bulk clks: %d\n", ret);
return ret;
}
return 0;
}
static int rk_pcie_resource_get(struct platform_device *pdev,
struct rk_pcie *rk_pcie)
{
struct resource *dbi_base;
struct resource *apb_base;
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"pcie-dbi");
if (!dbi_base) {
dev_err(&pdev->dev, "get pcie-dbi failed\n");
return -ENODEV;
}
rk_pcie->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
if (IS_ERR(rk_pcie->dbi_base))
return PTR_ERR(rk_pcie->dbi_base);
rk_pcie->pci->dbi_base = rk_pcie->dbi_base;
rk_pcie->pci->dbi_base2 = rk_pcie->pci->dbi_base + PCIE_TYPE0_HDR_DBI2_OFFSET;
apb_base = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"pcie-apb");
if (!apb_base) {
dev_err(&pdev->dev, "get pcie-apb failed\n");
return -ENODEV;
}
rk_pcie->apb_base = devm_ioremap_resource(&pdev->dev, apb_base);
if (IS_ERR(rk_pcie->apb_base))
return PTR_ERR(rk_pcie->apb_base);
/*
* Rest the device before enabling power because some of the
* platforms may use external refclk input with the some power
* rail connect to 100MHz OSC chip. So once the power is up for
* the slot and the refclk is available, which isn't quite follow
* the spec. We should make sure it is in reset state before
* everthing's ready.
*/
rk_pcie->rst_gpio = devm_gpiod_get_optional(&pdev->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(rk_pcie->rst_gpio)) {
dev_err(&pdev->dev, "invalid reset-gpios property in node\n");
return PTR_ERR(rk_pcie->rst_gpio);
}
if (device_property_read_u32(&pdev->dev, "rockchip,perst-inactive-ms",
&rk_pcie->perst_inactive_ms))
rk_pcie->perst_inactive_ms = 200;
rk_pcie->prsnt_gpio = devm_gpiod_get_optional(&pdev->dev, "prsnt", GPIOD_IN);
if (IS_ERR_OR_NULL(rk_pcie->prsnt_gpio))
dev_info(&pdev->dev, "invalid prsnt-gpios property in node\n");
return 0;
}
static int rk_pcie_phy_init(struct rk_pcie *rk_pcie)
{
int ret;
struct device *dev = rk_pcie->pci->dev;
rk_pcie->phy = devm_phy_optional_get(dev, "pcie-phy");
if (IS_ERR(rk_pcie->phy)) {
if (PTR_ERR(rk_pcie->phy) != -EPROBE_DEFER)
dev_info(dev, "missing phy\n");
return PTR_ERR(rk_pcie->phy);
}
ret = phy_set_mode_ext(rk_pcie->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_RC);
if (ret) {
dev_err(dev, "fail to set phy to rc mode, err %d\n", ret);
return ret;
}
if (rk_pcie->bifurcation)
phy_set_mode_ext(rk_pcie->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_BIFURCATION);
ret = phy_init(rk_pcie->phy);
if (ret < 0) {
dev_err(dev, "fail to init phy, err %d\n", ret);
return ret;
}
phy_power_on(rk_pcie->phy);
return 0;
}
static void rk_pcie_start_dma_rd(struct dma_trx_obj *obj, struct dma_table *cur, int ctr_off)
{
struct rk_pcie *rk_pcie = dev_get_drvdata(obj->dev);
@@ -655,6 +510,237 @@ static void rk_pcie_config_dma_dwc(struct dma_table *table)
table->start.chnl = table->chn;
}
static int rk_pcie_init_dma_trx(struct rk_pcie *rk_pcie)
{
if (!rk_pcie_udma_enabled(rk_pcie))
return 0;
rk_pcie->dma_obj = pcie_dw_dmatest_register(rk_pcie->pci->dev, true);
if (IS_ERR(rk_pcie->dma_obj)) {
dev_err(rk_pcie->pci->dev, "failed to prepare dmatest\n");
return -EINVAL;
}
/* Enable client write and read interrupt */
rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0xc000000);
/* Enable core write interrupt */
dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_MASK,
0x0);
/* Enable core read interrupt */
dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_MASK,
0x0);
rk_pcie->dma_obj->start_dma_func = rk_pcie_start_dma_dwc;
rk_pcie->dma_obj->config_dma_func = rk_pcie_config_dma_dwc;
return 0;
}
#ifdef MODULE
void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, size_t size, u32 val)
{
int ret;
if (pci->ops && pci->ops->write_dbi2) {
pci->ops->write_dbi2(pci, pci->dbi_base2, reg, size, val);
return;
}
ret = dw_pcie_write(pci->dbi_base2 + reg, size, val);
if (ret)
dev_err(pci->dev, "write DBI address failed\n");
}
#endif
static struct dw_pcie_host_ops rk_pcie_host_ops;
static int rk_add_pcie_port(struct rk_pcie *rk_pcie, struct platform_device *pdev)
{
int ret;
struct dw_pcie *pci = rk_pcie->pci;
struct dw_pcie_rp *pp = &pci->pp;
struct device *dev = pci->dev;
pp->ops = &rk_pcie_host_ops;
if (IS_ENABLED(CONFIG_PCI_MSI)) {
if (rk_pcie->msi_vector_num > 0) {
dev_info(dev, "max MSI vector is %d\n", rk_pcie->msi_vector_num);
pp->num_vectors = rk_pcie->msi_vector_num;
}
}
ret = dw_pcie_host_init(pp);
if (ret) {
dev_err(dev, "failed to initialize host\n");
return ret;
}
/* Disable BAR0 BAR1 */
dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_0, 0x0);
dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_1, 0x0);
return 0;
}
static int rk_pcie_resource_get(struct platform_device *pdev,
struct rk_pcie *rk_pcie)
{
struct resource *dbi_base;
struct resource *apb_base;
u32 val = 0;
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"pcie-dbi");
if (!dbi_base) {
dev_err(&pdev->dev, "get pcie-dbi failed\n");
return -ENODEV;
}
rk_pcie->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
if (IS_ERR(rk_pcie->dbi_base))
return PTR_ERR(rk_pcie->dbi_base);
rk_pcie->pci->dbi_base = rk_pcie->dbi_base;
rk_pcie->pci->dbi_base2 = rk_pcie->pci->dbi_base + PCIE_TYPE0_HDR_DBI2_OFFSET;
apb_base = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"pcie-apb");
if (!apb_base) {
dev_err(&pdev->dev, "get pcie-apb failed\n");
return -ENODEV;
}
rk_pcie->apb_base = devm_ioremap_resource(&pdev->dev, apb_base);
if (IS_ERR(rk_pcie->apb_base))
return PTR_ERR(rk_pcie->apb_base);
/*
* Rest the device before enabling power because some of the
* platforms may use external refclk input with the some power
* rail connect to 100MHz OSC chip. So once the power is up for
* the slot and the refclk is available, which isn't quite follow
* the spec. We should make sure it is in reset state before
* everthing's ready.
*/
rk_pcie->rst_gpio = devm_gpiod_get_optional(&pdev->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(rk_pcie->rst_gpio)) {
dev_err(&pdev->dev, "invalid reset-gpios property in node\n");
return PTR_ERR(rk_pcie->rst_gpio);
}
if (device_property_read_u32(&pdev->dev, "rockchip,perst-inactive-ms",
&rk_pcie->perst_inactive_ms))
rk_pcie->perst_inactive_ms = 200;
rk_pcie->prsnt_gpio = devm_gpiod_get_optional(&pdev->dev, "prsnt", GPIOD_IN);
if (IS_ERR_OR_NULL(rk_pcie->prsnt_gpio))
dev_info(&pdev->dev, "invalid prsnt-gpios property in node\n");
rk_pcie->clk_cnt = devm_clk_bulk_get_all(&pdev->dev, &rk_pcie->clks);
if (rk_pcie->clk_cnt < 1)
return -ENODEV;
rk_pcie->rsts = devm_reset_control_array_get_exclusive(&pdev->dev);
if (IS_ERR(rk_pcie->rsts)) {
dev_err(&pdev->dev, "failed to get reset lines\n");
return PTR_ERR(rk_pcie->rsts);
}
if (device_property_read_bool(&pdev->dev, "rockchip,bifurcation"))
rk_pcie->bifurcation = true;
rk_pcie->supports_clkreq = device_property_read_bool(&pdev->dev, "supports-clkreq");
if (device_property_read_bool(&pdev->dev, "hotplug-gpios") ||
device_property_read_bool(&pdev->dev, "hotplug-gpio")) {
rk_pcie->slot_pluggable = true;
dev_info(&pdev->dev, "support hotplug-gpios!\n");
}
/* Skip waiting for training to pass in system PM routine */
if (device_property_read_bool(&pdev->dev, "rockchip,skip-scan-in-resume"))
rk_pcie->skip_scan_in_resume = true;
/* Force into loopback master mode */
if (device_property_read_bool(&pdev->dev, "rockchip,lpbk-master")) {
rk_pcie->is_lpbk = true;
rk_pcie->is_signal_test = true;
}
/*
* Force into compliance mode
* comp_prst is a two dimensional array of which the first element
* stands for speed mode, and the second one is preset value encoding:
* [0] 0->SMA tool control the signal switch, 1/2/3 is for manual Gen setting
* [1] transmitter setting for manual Gen setting, valid only if [0] isn't zero.
*/
if (!device_property_read_u32_array(&pdev->dev, "rockchip,compliance-mode",
rk_pcie->comp_prst, 2)) {
WARN_ON_ONCE(rk_pcie->comp_prst[0] > 3 || rk_pcie->comp_prst[1] > 10);
if (!rk_pcie->comp_prst[0])
dev_info(&pdev->dev, "Auto compliance mode for SMA tool.\n");
else
dev_info(&pdev->dev, "compliance mode for soldered board Gen%d, P%d.\n",
rk_pcie->comp_prst[0], rk_pcie->comp_prst[1]);
rk_pcie->is_comp = true;
rk_pcie->is_signal_test = true;
}
retry_regulator:
rk_pcie->vpcie3v3 = devm_regulator_get_optional(&pdev->dev, "vpcie3v3");
if (IS_ERR(rk_pcie->vpcie3v3)) {
if (PTR_ERR(rk_pcie->vpcie3v3) != -ENODEV) {
if (IS_ENABLED(CONFIG_PCIE_RK_THREADED_INIT)) {
/* Deferred but in threaded context for most 10s */
msleep(20);
if (++val < 500)
goto retry_regulator;
}
return PTR_ERR(rk_pcie->vpcie3v3);
}
dev_info(&pdev->dev, "no vpcie3v3 regulator found\n");
}
return 0;
}
static int rk_pcie_phy_init(struct rk_pcie *rk_pcie)
{
int ret;
struct device *dev = rk_pcie->pci->dev;
rk_pcie->phy = devm_phy_optional_get(dev, "pcie-phy");
if (IS_ERR(rk_pcie->phy)) {
if (PTR_ERR(rk_pcie->phy) != -EPROBE_DEFER)
dev_info(dev, "missing phy\n");
return PTR_ERR(rk_pcie->phy);
}
ret = phy_set_mode_ext(rk_pcie->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_RC);
if (ret) {
dev_err(dev, "fail to set phy to rc mode, err %d\n", ret);
return ret;
}
if (rk_pcie->bifurcation)
phy_set_mode_ext(rk_pcie->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_BIFURCATION);
ret = phy_init(rk_pcie->phy);
if (ret < 0) {
dev_err(dev, "fail to init phy, err %d\n", ret);
return ret;
}
phy_power_on(rk_pcie->phy);
return 0;
}
static void rk_pcie_hot_rst_work(struct work_struct *work)
{
struct rk_pcie *rk_pcie = container_of(work, struct rk_pcie, hot_rst_work);
@@ -893,36 +979,6 @@ static int rk_pcie_init_irq_domain(struct rk_pcie *rockchip)
return 0;
}
static int rk_pcie_enable_power(struct rk_pcie *rk_pcie)
{
int ret = 0;
struct device *dev = rk_pcie->pci->dev;
if (IS_ERR(rk_pcie->vpcie3v3))
return ret;
ret = regulator_enable(rk_pcie->vpcie3v3);
if (ret)
dev_err(dev, "fail to enable vpcie3v3 regulator\n");
return ret;
}
static int rk_pcie_disable_power(struct rk_pcie *rk_pcie)
{
int ret = 0;
struct device *dev = rk_pcie->pci->dev;
if (IS_ERR(rk_pcie->vpcie3v3))
return ret;
ret = regulator_disable(rk_pcie->vpcie3v3);
if (ret)
dev_err(dev, "fail to disable vpcie3v3 regulator\n");
return ret;
}
#define RAS_DES_EVENT(ss, v) \
do { \
dw_pcie_writel_dbi(pcie->pci, cap_base + 8, v); \
@@ -1061,6 +1117,9 @@ static int rockchip_pcie_debugfs_init(struct rk_pcie *pcie)
{
struct dentry *file;
if (!IS_ENABLED(CONFIG_DEBUG_FS) || !pcie->have_rasdes)
return 0;
pcie->debugfs = debugfs_create_dir(dev_name(pcie->pci->dev), NULL);
if (!pcie->debugfs)
return -ENOMEM;
@@ -1115,6 +1174,50 @@ static const struct gpio_hotplug_slot_plat_ops rk_pcie_gpio_hp_plat_ops = {
.disable = rk_pcie_slot_disable,
};
static int rk_pcie_init_irq_and_wq(struct rk_pcie *rk_pcie, struct platform_device *pdev)
{
struct device *dev = rk_pcie->pci->dev;
int ret, irq;
/*
* Misc interrupts was masked by default. However, they will be
* unmasked by FW before jumpping into kernel. Mask all misc interrupts,
* as we don't need to ack them before registering irq. And they will be
* unmasked later.
*/
rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0xffffffff);
ret = rk_pcie_request_sys_irq(rk_pcie, pdev);
if (ret) {
dev_err(dev, "pcie irq init failed\n");
return ret;
}
/* Legacy interrupt is optional */
ret = rk_pcie_init_irq_domain(rk_pcie);
if (!ret) {
irq = platform_get_irq_byname(pdev, "legacy");
if (irq >= 0) {
irq_set_chained_handler_and_data(irq, rk_pcie_legacy_int_handler,
rk_pcie);
/* Unmask all legacy interrupt from INTA~INTD */
rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY,
UNMASK_ALL_LEGACY_INT);
} else {
dev_info(dev, "missing legacy IRQ resource\n");
}
}
rk_pcie->hot_rst_wq = create_singlethread_workqueue("rk_pcie_hot_rst_wq");
if (!rk_pcie->hot_rst_wq) {
dev_err(dev, "failed to create hot_rst workqueue\n");
return -ENOMEM;
}
INIT_WORK(&rk_pcie->hot_rst_work, rk_pcie_hot_rst_work);
return 0;
}
static int rk_pcie_really_probe(void *p)
{
struct platform_device *pdev = p;
@@ -1125,8 +1228,8 @@ static int rk_pcie_really_probe(void *p)
const struct of_device_id *match;
const struct rk_pcie_of_data *data;
u32 val = 0;
int irq;
/* 1. resource initialization */
match = of_match_device(rk_pcie_of_match, dev);
if (!match) {
ret = -EINVAL;
@@ -1147,22 +1250,21 @@ static int rk_pcie_really_probe(void *p)
goto release_driver;
}
/* 2. variables assignment */
rk_pcie->pci = pci;
rk_pcie->msi_vector_num = data ? data->msi_vector_num : 0;
pci->dev = dev;
pci->ops = &dw_pcie_ops;
platform_set_drvdata(pdev, rk_pcie);
if (data)
rk_pcie->msi_vector_num = data->msi_vector_num;
rk_pcie->pci = pci;
if (device_property_read_bool(dev, "rockchip,bifurcation"))
rk_pcie->bifurcation = true;
/* 3. firmware resource */
ret = rk_pcie_resource_get(pdev, rk_pcie);
if (ret) {
dev_err(dev, "resource init failed\n");
dev_err_probe(dev, ret, "resource init failed\n");
goto release_driver;
}
/* 4. hardware io settings */
if (!IS_ERR_OR_NULL(rk_pcie->prsnt_gpio)) {
if (!gpiod_get_value(rk_pcie->prsnt_gpio)) {
dev_info(dev, "device isn't present\n");
@@ -1171,137 +1273,57 @@ static int rk_pcie_really_probe(void *p)
}
}
rk_pcie->supports_clkreq = device_property_read_bool(dev, "supports-clkreq");
if (device_property_read_bool(dev, "hotplug-gpios") ||
device_property_read_bool(dev, "hotplug-gpio")) {
rk_pcie->slot_pluggable = true;
dev_info(dev, "support hotplug-gpios!\n");
}
retry_regulator:
/* DON'T MOVE ME: must be enable before phy init */
rk_pcie->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3");
if (IS_ERR(rk_pcie->vpcie3v3)) {
if (PTR_ERR(rk_pcie->vpcie3v3) != -ENODEV) {
if (IS_ENABLED(CONFIG_PCIE_RK_THREADED_INIT)) {
/* Deferred but in threaded context for most 10s */
msleep(20);
if (++val < 500)
goto retry_regulator;
}
ret = PTR_ERR(rk_pcie->vpcie3v3);
goto release_driver;
}
dev_info(dev, "no vpcie3v3 regulator found\n");
}
ret = rk_pcie_enable_power(rk_pcie);
if (ret)
goto release_driver;
ret = rk_pcie_phy_init(rk_pcie);
reset_control_deassert(rk_pcie->rsts);
ret = clk_bulk_prepare_enable(rk_pcie->clk_cnt, rk_pcie->clks);
if (ret) {
dev_err(dev, "phy init failed\n");
dev_err_probe(dev, ret, "clock init failed\n");
goto disable_vpcie3v3;
}
rk_pcie->rsts = devm_reset_control_array_get_exclusive(dev);
if (IS_ERR(rk_pcie->rsts)) {
ret = PTR_ERR(rk_pcie->rsts);
dev_err(dev, "failed to get reset lines\n");
goto disable_phy;
}
reset_control_deassert(rk_pcie->rsts);
ret = rk_pcie_clk_init(rk_pcie);
ret = rk_pcie_phy_init(rk_pcie);
if (ret) {
dev_err(dev, "clock init failed\n");
goto disable_phy;
}
/*
* Misc interrupts was masked by default. However, they will be
* unmasked by FW before jumpping into kernel. Mask all misc interrupts,
* as we don't need to ack them before registering irq. And they will be
* unmasked later.
*/
rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0xffffffff);
ret = rk_pcie_request_sys_irq(rk_pcie, pdev);
if (ret) {
dev_err(dev, "pcie irq init failed\n");
dev_err_probe(dev, ret, "phy init failed\n");
goto disable_clk;
}
platform_set_drvdata(pdev, rk_pcie);
/* 5. signal test and capability settings */
if (rk_pcie->is_lpbk) {
val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
val |= PORT_LINK_LPBK_ENABLE;
dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
}
if (rk_pcie->is_comp && rk_pcie->comp_prst[0]) {
val = dw_pcie_readl_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS);
val |= BIT(4) | rk_pcie->comp_prst[0] | (rk_pcie->comp_prst[1] << 12);
dw_pcie_writel_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS, val);
}
/* Enable RASDES Error event by default */
val = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_VNDR);
if (!val) {
dev_err(pci->dev, "Unable to find RASDES CAP!\n");
} else {
dw_pcie_writel_dbi(pci, val + 8, 0x1c);
dw_pcie_writel_dbi(pci, val + 8, 0x3);
rk_pcie->have_rasdes = true;
}
/* 6. software process */
ret = rk_pcie_init_irq_and_wq(rk_pcie, pdev);
if (ret)
goto disable_phy;
dw_pcie_dbi_ro_wr_en(pci);
rk_pcie_fast_link_setup(rk_pcie);
/* Legacy interrupt is optional */
ret = rk_pcie_init_irq_domain(rk_pcie);
if (!ret) {
irq = platform_get_irq_byname(pdev, "legacy");
if (irq >= 0) {
irq_set_chained_handler_and_data(irq, rk_pcie_legacy_int_handler,
rk_pcie);
/* Unmask all legacy interrupt from INTA~INTD */
rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY,
UNMASK_ALL_LEGACY_INT);
} else {
dev_info(dev, "missing legacy IRQ resource\n");
}
}
/* Set PCIe RC mode */
rk_pcie_set_mode(rk_pcie);
/* Force into loopback master mode */
if (device_property_read_bool(dev, "rockchip,lpbk-master")) {
val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
val |= PORT_LINK_LPBK_ENABLE;
dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
rk_pcie->is_signal_test = true;
}
/*
* Force into compliance mode
* comp_prst is a two dimensional array of which the first element
* stands for speed mode, and the second one is preset value encoding:
* [0] 0->SMA tool control the signal switch, 1/2/3 is for manual Gen setting
* [1] transmitter setting for manual Gen setting, valid only if [0] isn't zero.
*/
if (!device_property_read_u32_array(dev, "rockchip,compliance-mode",
rk_pcie->comp_prst, 2)) {
BUG_ON(rk_pcie->comp_prst[0] > 3 || rk_pcie->comp_prst[1] > 10);
if (!rk_pcie->comp_prst[0]) {
dev_info(dev, "Auto compliance mode for SMA tool.\n");
} else {
dev_info(dev, "compliance mode for soldered board Gen%d, P%d.\n",
rk_pcie->comp_prst[0], rk_pcie->comp_prst[1]);
val = dw_pcie_readl_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS);
val |= BIT(4) | rk_pcie->comp_prst[0] | (rk_pcie->comp_prst[1] << 12);
dw_pcie_writel_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS, val);
}
rk_pcie->is_signal_test = true;
}
/* Skip waiting for training to pass in system PM routine */
if (device_property_read_bool(dev, "rockchip,skip-scan-in-resume"))
rk_pcie->skip_scan_in_resume = true;
rk_pcie->hot_rst_wq = create_singlethread_workqueue("rk_pcie_hot_rst_wq");
if (!rk_pcie->hot_rst_wq) {
dev_err(dev, "failed to create hot_rst workqueue\n");
ret = -ENOMEM;
goto remove_irq_domain;
}
INIT_WORK(&rk_pcie->hot_rst_work, rk_pcie_hot_rst_work);
rk_pcie_set_rc_mode(rk_pcie);
ret = rk_add_pcie_port(rk_pcie, pdev);
@@ -1309,7 +1331,7 @@ retry_regulator:
return 0;
if (ret && !rk_pcie->slot_pluggable)
goto remove_rst_wq;
goto deinit_irq_and_wq;
if (rk_pcie->slot_pluggable) {
rk_pcie->hp_slot.plat_ops = &rk_pcie_gpio_hp_plat_ops;
@@ -1327,50 +1349,31 @@ retry_regulator:
ret = rk_pcie_init_dma_trx(rk_pcie);
if (ret) {
dev_err(dev, "failed to add dma extension\n");
goto remove_rst_wq;
dev_err_probe(dev, ret, "failed to add dma extension\n");
goto deinit_irq_and_wq;
}
if (rk_pcie->dma_obj) {
rk_pcie->dma_obj->start_dma_func = rk_pcie_start_dma_dwc;
rk_pcie->dma_obj->config_dma_func = rk_pcie_config_dma_dwc;
}
ret = rockchip_pcie_debugfs_init(rk_pcie);
if (ret < 0)
dev_err_probe(dev, ret, "failed to setup debugfs\n");
dw_pcie_dbi_ro_wr_dis(pci);
/* 7. framework misc settings */
device_init_wakeup(dev, true);
/* Enable async system PM for multiports SoC */
device_enable_async_suspend(dev);
if (IS_ENABLED(CONFIG_DEBUG_FS)) {
ret = rockchip_pcie_debugfs_init(rk_pcie);
if (ret < 0)
dev_err(dev, "failed to setup debugfs: %d\n", ret);
/* Enable RASDES Error event by default */
val = dw_pcie_find_ext_capability(rk_pcie->pci, PCI_EXT_CAP_ID_VNDR);
if (!val) {
dev_err(dev, "Not able to find RASDES CAP!\n");
return 0;
}
dw_pcie_writel_dbi(rk_pcie->pci, val + 8, 0x1c);
dw_pcie_writel_dbi(rk_pcie->pci, val + 8, 0x3);
}
device_enable_async_suspend(dev); /* Enable async system PM for multiports SoC */
return 0;
remove_rst_wq:
deinit_irq_and_wq:
destroy_workqueue(rk_pcie->hot_rst_wq);
remove_irq_domain:
if (rk_pcie->irq_domain)
irq_domain_remove(rk_pcie->irq_domain);
disable_clk:
clk_bulk_disable_unprepare(rk_pcie->clk_cnt, rk_pcie->clks);
disable_phy:
phy_power_off(rk_pcie->phy);
phy_exit(rk_pcie->phy);
disable_clk:
clk_bulk_disable_unprepare(rk_pcie->clk_cnt, rk_pcie->clks);
disable_vpcie3v3:
rk_pcie_disable_power(rk_pcie);
release_driver:
@@ -1386,10 +1389,8 @@ static int rk_pcie_probe(struct platform_device *pdev)
struct task_struct *tsk;
tsk = kthread_run(rk_pcie_really_probe, pdev, "rk-pcie");
if (IS_ERR(tsk)) {
dev_err(&pdev->dev, "start rk-pcie thread failed\n");
return PTR_ERR(tsk);
}
if (IS_ERR(tsk))
return dev_err_probe(&pdev->dev, PTR_ERR(tsk), "start rk-pcie thread failed\n");
return 0;
}
@@ -1601,8 +1602,7 @@ static int __maybe_unused rockchip_dw_pcie_resume(struct device *dev)
rk_pcie_fast_link_setup(rk_pcie);
/* Set PCIe RC mode */
rk_pcie_set_mode(rk_pcie);
rk_pcie_set_rc_mode(rk_pcie);
dw_pcie_setup_rc(&rk_pcie->pci->pp);

View File

@@ -110,10 +110,14 @@ int exfat_load_bitmap(struct super_block *sb)
return -EIO;
type = exfat_get_entry_type(ep);
if (type == TYPE_UNUSED)
if (type == TYPE_UNUSED) {
brelse(bh);
break;
if (type != TYPE_BITMAP)
}
if (type != TYPE_BITMAP) {
brelse(bh);
continue;
}
if (ep->dentry.bitmap.flags == 0x0) {
int err;

View File

@@ -76,6 +76,10 @@ struct multicodecs_data {
const struct adc_keys_button *map;
struct input_dev *input;
struct input_dev_poller *poller;
int slots;
int slot_width;
unsigned int tx_slot_mask;
unsigned int rx_slot_mask;
};
static const unsigned int headset_extcon_cable[] = {
@@ -399,7 +403,9 @@ static int rk_dailink_init(struct snd_soc_pcm_runtime *rtd)
struct multicodecs_data *mc_data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_card *card = rtd->card;
struct snd_soc_jack *jack_headset;
int ret, irq;
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai;
int ret, irq, i;
struct snd_soc_jack_pin *pins;
struct snd_soc_jack_zone *zones;
struct snd_soc_jack_pin jack_pins[] = {
@@ -427,6 +433,30 @@ static int rk_dailink_init(struct snd_soc_pcm_runtime *rtd)
}
};
if (mc_data->slots) {
ret = snd_soc_dai_set_tdm_slot(cpu_dai,
mc_data->tx_slot_mask,
mc_data->rx_slot_mask,
mc_data->slots,
mc_data->slot_width);
if (ret && ret != -EOPNOTSUPP) {
dev_err(card->dev, "cpu_dai: set_tdm_slot error\n");
return ret;
}
for_each_rtd_codec_dais(rtd, i, codec_dai) {
ret = snd_soc_dai_set_tdm_slot(codec_dai,
mc_data->tx_slot_mask,
mc_data->rx_slot_mask,
mc_data->slots,
mc_data->slot_width);
if (ret && ret != -EOPNOTSUPP) {
dev_err(card->dev, "codec_dai: set_tdm_slot error\n");
return ret;
}
}
}
if ((!mc_data->codec_hp_det) && (gpiod_to_irq(mc_data->hp_det_gpio) < 0)) {
dev_info(card->dev, "Don't need to map headset detect gpio to irq\n");
return 0;
@@ -804,6 +834,15 @@ static int rk_multicodecs_probe(struct platform_device *pdev)
mc_data->dai_link[0].platforms->of_node = mc_data->dai_link[0].cpus->of_node;
ret = snd_soc_of_parse_tdm_slot(np,
&mc_data->tx_slot_mask,
&mc_data->rx_slot_mask,
&mc_data->slots,
&mc_data->slot_width);
if (ret < 0) {
dev_err(&pdev->dev, "snd_soc_of_parse_tdm_slot failed: %d\n", ret);
return ret;
}
asrc_np = of_parse_phandle(np, "rockchip,asrc", 0);
if (asrc_np) {
mc_data->dai_link[1].cpus->of_node = asrc_np;