mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
PCI: rockchip: dw: Support bar2 memory map
Rerseved memory for bar2 mapping by the dts property
"memory-region", the bar resource mapping rule:
- bar0 4MB
- bar2 64MB
for example:
reserved-memory {
...
bar0_region: bar0-region@0x3c000000 {
reg = <0x0 0x3c000000 0x0 0x00400000>;
};
bar2_region: bar2-region@0x40000000 {
reg = <0x0 0x40000000 0x0 0x04000000>;
};
};
&pcie3x4 {
...
memory-region = <&bar0_region>, <&bar2_region>;
memory-region-names = "bar0", "bar2";
...
};
The rule is flexble and change by user as they want.
Change-Id: I1b866919f81892ad5326fb93896384c22c54fe74
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
This commit is contained in:
@@ -105,6 +105,8 @@
|
||||
|
||||
#define PCIE_EP_OBJ_INFO_DRV_VERSION 0x00000001
|
||||
|
||||
#define PCIE_BAR_MAX_NUM 6
|
||||
|
||||
struct rockchip_pcie {
|
||||
struct dw_pcie pci;
|
||||
void __iomem *apb_base;
|
||||
@@ -119,10 +121,10 @@ struct rockchip_pcie {
|
||||
u32 num_ib_windows;
|
||||
u32 num_ob_windows;
|
||||
phys_addr_t *outbound_addr;
|
||||
u8 bar_to_atu[6];
|
||||
dma_addr_t ib_target_address;
|
||||
u32 ib_target_size;
|
||||
void *ib_target_base;
|
||||
u8 bar_to_atu[PCIE_BAR_MAX_NUM];
|
||||
dma_addr_t ib_target_address[PCIE_BAR_MAX_NUM];
|
||||
u32 ib_target_size[PCIE_BAR_MAX_NUM];
|
||||
void *ib_target_base[PCIE_BAR_MAX_NUM];
|
||||
struct dma_trx_obj *dma_obj;
|
||||
struct fasync_struct *async;
|
||||
phys_addr_t dbi_base_physical;
|
||||
@@ -193,6 +195,8 @@ static int rockchip_pcie_resource_get(struct platform_device *pdev,
|
||||
struct resource *dbi_base;
|
||||
struct device_node *mem;
|
||||
struct resource reg;
|
||||
char name[8];
|
||||
int i, idx;
|
||||
|
||||
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
"pcie-dbi");
|
||||
@@ -259,27 +263,42 @@ static int rockchip_pcie_resource_get(struct platform_device *pdev,
|
||||
|
||||
rockchip->outbound_addr = addr;
|
||||
|
||||
mem = of_parse_phandle(np, "memory-region", 0);
|
||||
if (!mem) {
|
||||
dev_err(dev, "missing \"memory-region\" property\n");
|
||||
return -ENODEV;
|
||||
for (i = 0; i < PCIE_BAR_MAX_NUM; i++) {
|
||||
snprintf(name, sizeof(name), "bar%d", i);
|
||||
idx = of_property_match_string(np, "memory-region-names", name);
|
||||
if (idx < 0)
|
||||
continue;
|
||||
|
||||
mem = of_parse_phandle(np, "memory-region", idx);
|
||||
if (!mem) {
|
||||
dev_err(dev, "missing \"memory-region\" %s property\n", name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(mem, 0, ®);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "missing \"reg\" %s property\n", name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rockchip->ib_target_address[i] = reg.start;
|
||||
rockchip->ib_target_size[i] = resource_size(®);
|
||||
rockchip->ib_target_base[i] = rockchip_pcie_map_kernel(reg.start,
|
||||
resource_size(®));
|
||||
dev_info(dev, "%s: assigned [0x%llx-%llx]\n", name, rockchip->ib_target_address[i],
|
||||
rockchip->ib_target_address[i] + rockchip->ib_target_size[i] - 1);
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(mem, 0, ®);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "missing \"reg\" property\n");
|
||||
if (rockchip->ib_target_size[0]) {
|
||||
rockchip->obj_info = (struct pcie_ep_obj_info *)rockchip->ib_target_base[0];
|
||||
memset_io(rockchip->obj_info, 0, sizeof(struct pcie_ep_obj_info));
|
||||
rockchip->obj_info->magic = PCIE_EP_OBJ_INFO_MAGIC;
|
||||
rockchip->obj_info->version = PCIE_EP_OBJ_INFO_DRV_VERSION;
|
||||
} else {
|
||||
dev_err(dev, "missing bar0 memory region\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rockchip->ib_target_address = reg.start;
|
||||
rockchip->ib_target_size = resource_size(®);
|
||||
rockchip->ib_target_base = rockchip_pcie_map_kernel(reg.start,
|
||||
resource_size(®));
|
||||
rockchip->obj_info = (struct pcie_ep_obj_info *)rockchip->ib_target_base;
|
||||
memset_io(rockchip->obj_info, 0, sizeof(struct pcie_ep_obj_info));
|
||||
rockchip->obj_info->magic = PCIE_EP_OBJ_INFO_MAGIC;
|
||||
rockchip->obj_info->version = PCIE_EP_OBJ_INFO_DRV_VERSION;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -493,7 +512,7 @@ static void rockchip_pcie_resize_bar(struct rockchip_pcie *rockchip)
|
||||
|
||||
resbar_base = rockchip_pci_find_resbar_capability(rockchip);
|
||||
|
||||
/* Resize BAR0 4M 32bits, BAR2 64M 64bits-pref */
|
||||
/* Resize BAR0 4M 32bits, BAR2 64M 64bits-pref, BAR4 1MB 32bits */
|
||||
bar = BAR_0;
|
||||
dw_pcie_writel_dbi(pci, resbar_base + 0x4 + bar * 0x8, 0xfffff0);
|
||||
dw_pcie_writel_dbi(pci, resbar_base + 0x8 + bar * 0x8, 0x2c0);
|
||||
@@ -510,7 +529,7 @@ static void rockchip_pcie_resize_bar(struct rockchip_pcie *rockchip)
|
||||
dw_pcie_writel_dbi(pci, resbar_base + 0x8 + bar * 0x8, 0xc0);
|
||||
rockchip_pcie_ep_set_bar_flag(rockchip, bar, PCI_BASE_ADDRESS_MEM_TYPE_32);
|
||||
|
||||
/* Disable BAR1 BAR4 BAR5*/
|
||||
/* Disable BAR1 BAR5*/
|
||||
bar = BAR_1;
|
||||
dw_pcie_writel_dbi(pci, PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + bar * 4, 0);
|
||||
bar = BAR_5;
|
||||
@@ -525,14 +544,13 @@ static void rockchip_pcie_init_id(struct rockchip_pcie *rockchip)
|
||||
dw_pcie_writew_dbi(pci, PCI_CLASS_DEVICE, 0x0580);
|
||||
}
|
||||
|
||||
static int rockchip_pcie_ep_set_bar(struct rockchip_pcie *rockchip)
|
||||
static int rockchip_pcie_ep_set_bar(struct rockchip_pcie *rockchip, enum pci_barno bar,
|
||||
dma_addr_t cpu_addr)
|
||||
{
|
||||
int ret;
|
||||
u32 free_win;
|
||||
struct dw_pcie *pci = &rockchip->pci;
|
||||
enum pci_barno bar;
|
||||
enum dw_pcie_as_type as_type;
|
||||
dma_addr_t cpu_addr;
|
||||
|
||||
free_win = find_first_zero_bit(rockchip->ib_window_map,
|
||||
rockchip->num_ib_windows);
|
||||
@@ -542,8 +560,6 @@ static int rockchip_pcie_ep_set_bar(struct rockchip_pcie *rockchip)
|
||||
}
|
||||
|
||||
as_type = DW_PCIE_AS_MEM;
|
||||
bar = BAR_0;
|
||||
cpu_addr = rockchip->ib_target_address;
|
||||
|
||||
ret = dw_pcie_prog_inbound_atu(pci, 0, free_win, bar, cpu_addr, as_type);
|
||||
if (ret < 0) {
|
||||
@@ -555,7 +571,6 @@ static int rockchip_pcie_ep_set_bar(struct rockchip_pcie *rockchip)
|
||||
set_bit(free_win, rockchip->ib_window_map);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void rockchip_pcie_fast_link_setup(struct rockchip_pcie *rockchip)
|
||||
@@ -977,7 +992,7 @@ static long pcie_ep_ioctl(struct file *file, unsigned int cmd, unsigned long arg
|
||||
rockchip_pcie_raise_msi_irq(rockchip, PCIe_CLIENT_MSI_OBJ_IRQ);
|
||||
break;
|
||||
case PCIE_EP_GET_USER_INFO:
|
||||
msg.bar0_phys_addr = rockchip->ib_target_address;
|
||||
msg.bar0_phys_addr = rockchip->ib_target_address[0];
|
||||
|
||||
ret = copy_to_user(uarg, &msg, sizeof(msg));
|
||||
if (ret) {
|
||||
@@ -1021,11 +1036,18 @@ static int pcie_ep_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
addr = rockchip->dbi_base_physical;
|
||||
break;
|
||||
case PCIE_EP_MMAP_RESOURCE_BAR0:
|
||||
if (size > rockchip->ib_target_size) {
|
||||
if (size > rockchip->ib_target_size[0]) {
|
||||
dev_warn(rockchip->pci.dev, "bar0 mmap size is out of limitation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
addr = rockchip->ib_target_address;
|
||||
addr = rockchip->ib_target_address[0];
|
||||
break;
|
||||
case PCIE_EP_MMAP_RESOURCE_BAR2:
|
||||
if (size > rockchip->ib_target_size[2]) {
|
||||
dev_warn(rockchip->pci.dev, "bar2 mmap size is out of limitation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
addr = rockchip->ib_target_address[2];
|
||||
break;
|
||||
default:
|
||||
dev_err(rockchip->pci.dev, "cur mmap_res %d is unsurreport\n", rockchip->cur_mmap_res);
|
||||
@@ -1071,13 +1093,13 @@ static int rockchip_pcie_add_misc(struct rockchip_pcie *rockchip)
|
||||
|
||||
ret = misc_register(&pcie_dev->dev);
|
||||
if (ret) {
|
||||
pr_err("pcie: failed to register misc device.\n");
|
||||
dev_err(rockchip->pci.dev, "pcie: failed to register misc device.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
pcie_dev->pcie = rockchip;
|
||||
|
||||
pr_info("register misc device pcie-dev\n");
|
||||
dev_info(rockchip->pci.dev, "register misc device pcie_ep\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1087,7 +1109,7 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct rockchip_pcie *rockchip;
|
||||
int ret;
|
||||
int retry;
|
||||
int retry, i;
|
||||
|
||||
rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL);
|
||||
if (!rockchip)
|
||||
@@ -1123,8 +1145,10 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
|
||||
goto disable_regulator;
|
||||
|
||||
if (dw_pcie_link_up(&rockchip->pci)) {
|
||||
pr_info("%s, %d, already linkup\n", __func__, __LINE__);
|
||||
dev_info(dev, "already linkup\n");
|
||||
goto already_linkup;
|
||||
} else {
|
||||
dev_info(dev, "initial\n");
|
||||
}
|
||||
|
||||
ret = rockchip_pcie_phy_init(rockchip);
|
||||
@@ -1173,7 +1197,9 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
|
||||
|
||||
already_linkup:
|
||||
rockchip->pci.iatu_unroll_enabled = rockchip_pcie_iatu_unroll_enabled(&rockchip->pci);
|
||||
rockchip_pcie_ep_set_bar(rockchip);
|
||||
for (i = 0; i < PCIE_BAR_MAX_NUM; i++)
|
||||
if (rockchip->ib_target_size[i])
|
||||
rockchip_pcie_ep_set_bar(rockchip, i, rockchip->ib_target_address[i]);
|
||||
|
||||
ret = rockchip_pcie_init_dma_trx(rockchip);
|
||||
if (ret) {
|
||||
|
||||
Reference in New Issue
Block a user