summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAndy Fleming <afleming@freescale.com>2013-07-24 20:23:52 (GMT)
committerAndy Fleming <afleming@freescale.com>2013-07-24 20:23:52 (GMT)
commita8d022f84c57846be4b39ff740f86c8454c78b52 (patch)
treee6b54eff890fdc682a0ffda940f051fc6229b756 /drivers
parentd14ad9193b5971f9028e63d45c3f6827c3ba8a2e (diff)
parente9f747c6bbdd5aa6642e2921ae1fd1f10e8f8a43 (diff)
downloadlinux-fsl-qoriq-a8d022f84c57846be4b39ff740f86c8454c78b52.tar.xz
Merge remote-tracking branch 'fsl_devel/b4860rev2' into sdk1.4
Diffstat (limited to 'drivers')
-rw-r--r--drivers/iommu/fsl_pamu.c53
-rw-r--r--drivers/iommu/fsl_pamu.h8
-rw-r--r--drivers/iommu/fsl_pamu_domain.c187
-rw-r--r--drivers/iommu/fsl_pamu_domain.h12
-rw-r--r--drivers/staging/fsl_qbman/qman_driver.c1
5 files changed, 206 insertions, 55 deletions
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index 1f69fd1..4d466d6 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -35,11 +35,6 @@
#include "fsl_pamu.h"
-/* define indexes for each operation mapping scenario */
-#define OMI_QMAN 0x00
-#define OMI_FMAN 0x01
-#define OMI_QMAN_PRIV 0x02
-#define OMI_CAAM 0x03
/* Handling access violations */
#define make64(high, low) (((u64)(high) << 32) | (low))
@@ -278,7 +273,7 @@ void pamu_free_subwins(int liodn)
* Function used for updating stash destination for the coressponding
* LIODN.
*/
-int pamu_update_paace_stash(int liodn, u32 subwin, u32 value)
+int pamu_update_paace_field(int liodn, u32 subwin, int field, u32 value)
{
struct paace *paace;
@@ -293,8 +288,19 @@ int pamu_update_paace_stash(int liodn, u32 subwin, u32 value)
return -ENOENT;
}
}
- set_bf(paace->impl_attr, PAACE_IA_CID, value);
+ switch (field) {
+ case PAACE_STASH_FIELD:
+ set_bf(paace->impl_attr, PAACE_IA_CID, value);
+ break;
+ case PAACE_OMI_FIELD:
+ set_bf(paace->impl_attr, PAACE_IA_OTM, PAACE_OTM_INDEXED);
+ paace->op_encode.index_ot.omi = value;
+ break;
+ default:
+ pr_debug("Invalid field, can't update\n");
+ return -EINVAL;
+ }
mb();
return 0;
@@ -611,6 +617,7 @@ found_cpu_node:
#define QMAN_PORTAL_PAACE 2
#define BMAN_PAACE 3
#define FMAN_PAACE 4
+#define PMAN_PAACE 5
/**
* Setup operation mapping and stash destinations for QMAN and QMAN portal.
@@ -646,6 +653,10 @@ static void setup_dpaa_paace(struct paace *ppaace, int paace_type)
set_bf(ppaace->impl_attr, PAACE_IA_CID,
get_stash_id(IOMMU_ATTR_CACHE_L3, 0));
break;
+ case PMAN_PAACE:
+ set_bf(ppaace->impl_attr, PAACE_IA_OTM, PAACE_OTM_INDEXED);
+ ppaace->op_encode.index_ot.omi = OMI_PMAN;
+ break;
}
}
@@ -690,6 +701,32 @@ static void __init setup_omt(struct ome *omt)
ome = &omt[OMI_CAAM];
ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_READI;
ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WRITE;
+
+ /* Configure OMI_PMAN */
+ ome = &omt[OMI_PMAN];
+ ome->moe[IOE_DIRECT0_IDX] = EOE_LDEC | EOE_VALID;
+ ome->moe[IOE_DIRECT1_IDX] = EOE_LDEC | EOE_VALID;
+
+ /* Configure OMI_DMA */
+ ome = &omt[OMI_DMA];
+ ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_RSA;
+ ome->moe[IOE_EREAD0_IDX] = EOE_VALID | EOE_RSA;
+ ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WWSA;
+ ome->moe[IOE_EWRITE0_IDX] = EOE_VALID | EOE_WWSA;
+
+ /* Configure OMI_DMA_READI */
+ ome = &omt[OMI_DMA_READI];
+ ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_READI;
+ ome->moe[IOE_EREAD0_IDX] = EOE_VALID | EOE_READI;
+ ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WWSA;
+ ome->moe[IOE_EWRITE0_IDX] = EOE_VALID | EOE_WWSA;
+
+ /* Configure OMI_MAPLE */
+ ome = &omt[OMI_MAPLE];
+ ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_RSA;
+ ome->moe[IOE_EREAD0_IDX] = EOE_VALID | EOE_RSA;
+ ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WWSA;
+ ome->moe[IOE_EWRITE0_IDX] = EOE_VALID | EOE_WWSA;
}
/*
@@ -809,6 +846,8 @@ static void __init setup_liodns(void)
setup_dpaa_paace(ppaace, QMAN_PAACE);
if (of_device_is_compatible(node, "fsl,bman"))
setup_dpaa_paace(ppaace, BMAN_PAACE);
+ if (of_device_is_compatible(node, "fsl,pman"))
+ setup_dpaa_paace(ppaace, PMAN_PAACE);
#ifdef CONFIG_FSL_FMAN_CPC_STASH
if (of_device_is_compatible(node, "fsl,fman-port-10g-rx") ||
of_device_is_compatible(node, "fsl,fman-port-1g-rx"))
diff --git a/drivers/iommu/fsl_pamu.h b/drivers/iommu/fsl_pamu.h
index 83cbd26..fd9dd6d 100644
--- a/drivers/iommu/fsl_pamu.h
+++ b/drivers/iommu/fsl_pamu.h
@@ -384,6 +384,12 @@ struct ome {
#define EOE_WWSAOL 0x1e /* Write with stash allocate only and lock */
#define EOE_VALID 0x80
+enum paace_field {
+ PAACE_STASH_FIELD,
+ PAACE_OMI_FIELD,
+ PAACE_FIELD_MAX,
+};
+
/* Function prototypes */
int pamu_domain_init(void);
int pamu_enable_liodn(int liodn);
@@ -398,7 +404,7 @@ int pamu_config_spaace(int liodn, u32 subwin_cnt, u32 subwin_addr,
u32 get_stash_id(u32 stash_dest_hint, u32 vcpu);
void get_ome_index(u32 *omi_index, struct device *dev);
-int pamu_update_paace_stash(int liodn, u32 subwin, u32 value);
+int pamu_update_paace_field(int liodn, u32 subwin, int field, u32 value);
int pamu_disable_spaace(int liodn, u32 subwin);
u32 pamu_get_max_subwin_cnt(void);
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index 5b54505..99c182d 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -122,10 +122,10 @@ static int map_subwins(int liodn, struct fsl_dma_domain *dma_domain)
spin_lock(&iommu_lock);
ret = pamu_config_spaace(liodn, dma_domain->win_cnt, i,
sub_win_ptr[i].size,
- ~(u32)0,
+ sub_win_ptr[i].omi,
rpn,
dma_domain->snoop_id,
- dma_domain->stash_id,
+ sub_win_ptr[i].stash_id,
(i > 0) ? 1 : 0,
sub_win_ptr[i].prot);
spin_unlock(&iommu_lock);
@@ -149,9 +149,9 @@ static int map_win(int liodn, struct fsl_dma_domain *dma_domain)
spin_lock(&iommu_lock);
ret = pamu_config_ppaace(liodn, wnd_addr,
wnd->size,
- ~(u32)0,
+ wnd->omi,
wnd->paddr >> PAMU_PAGE_SHIFT,
- dma_domain->snoop_id, dma_domain->stash_id,
+ dma_domain->snoop_id, wnd->stash_id,
0, wnd->prot);
spin_unlock(&iommu_lock);
if (ret)
@@ -181,10 +181,10 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr
if (dma_domain->win_cnt > 1) {
ret = pamu_config_spaace(liodn, dma_domain->win_cnt, wnd_nr,
wnd->size,
- ~(u32)0,
+ wnd->omi,
wnd->paddr >> PAMU_PAGE_SHIFT,
dma_domain->snoop_id,
- dma_domain->stash_id,
+ wnd->stash_id,
(wnd_nr > 0) ? 1 : 0,
wnd->prot);
if (ret)
@@ -196,9 +196,9 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr
ret = pamu_config_ppaace(liodn, wnd_addr,
wnd->size,
- ~(u32)0,
+ wnd->omi,
wnd->paddr >> PAMU_PAGE_SHIFT,
- dma_domain->snoop_id, dma_domain->stash_id,
+ dma_domain->snoop_id, wnd->stash_id,
0, wnd->prot);
if (ret)
pr_err("Window reconfiguration failed for liodn %d\n", liodn);
@@ -209,29 +209,31 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr
return ret;
}
-static int update_liodn_stash(int liodn, struct fsl_dma_domain *dma_domain,
- u32 val)
+struct pamu_attr_info {
+ u32 window;
+ int field;
+ u32 value;
+};
+
+static int update_liodn_attr(int liodn, struct fsl_dma_domain *dma_domain,
+ struct pamu_attr_info *attr_info)
{
int ret = 0, i;
spin_lock(&iommu_lock);
- if (!dma_domain->win_cnt) {
- ret = pamu_update_paace_stash(liodn, 0, val);
- if (ret) {
- pr_err("Failed to update PAACE field for liodn %d\n ", liodn);
- spin_unlock(&iommu_lock);
- return ret;
- }
- } else {
+
+
+ if (~attr_info->window == 0) {
for (i = 0; i < dma_domain->win_cnt; i++) {
- ret = pamu_update_paace_stash(liodn, i, val);
- if (ret) {
- pr_err("Failed to update SPAACE %d field for liodn %d\n ", i, liodn);
- spin_unlock(&iommu_lock);
- return ret;
- }
+ ret = pamu_update_paace_field(liodn, i, attr_info->field,
+ attr_info->value);
+ if (ret)
+ break;
}
- }
+ } else
+ ret = pamu_update_paace_field(liodn, attr_info->window, attr_info->field,
+ attr_info->value);
+
spin_unlock(&iommu_lock);
return ret;
@@ -263,7 +265,7 @@ static int pamu_set_liodn(int liodn, struct device *dev,
if (!ret)
ret = pamu_config_ppaace(liodn, window_addr, window_size, omi_index,
0, dma_domain->snoop_id,
- dma_domain->stash_id, win_cnt, 0);
+ ~(u32)0, win_cnt, 0);
spin_unlock(&iommu_lock);
if (ret) {
pr_err("PAMU PAACE configuration failed for liodn %d, win_cnt =%d\n", liodn, win_cnt);
@@ -279,7 +281,7 @@ static int pamu_set_liodn(int liodn, struct device *dev,
ret = pamu_config_spaace(liodn, win_cnt, i,
subwin_size, omi_index,
0, dma_domain->snoop_id,
- dma_domain->stash_id,
+ ~(u32)0,
0, 0);
spin_unlock(&iommu_lock);
if (ret) {
@@ -320,7 +322,6 @@ static struct fsl_dma_domain *iommu_alloc_dma_domain(void)
if (!domain)
return NULL;
- domain->stash_id = ~(u32)0;
domain->snoop_id = ~(u32)0;
domain->win_cnt = pamu_get_max_subwin_cnt();
domain->geom_size = 0;
@@ -476,15 +477,20 @@ static int pamu_set_domain_geometry(struct fsl_dma_domain *dma_domain,
return ret;
}
-/* Update stash destination for all LIODNs associated with the domain */
-static int update_domain_stash(struct fsl_dma_domain *dma_domain, u32 val)
+/*
+ * Update attribute for all LIODNs associated with the domain
+ *
+ */
+static int update_domain_attr(struct fsl_dma_domain *dma_domain,
+ struct pamu_attr_info *attr_info)
{
struct device_domain_info *info;
int ret = 0;
if (!list_empty(&dma_domain->devices)) {
list_for_each_entry(info, &dma_domain->devices, link) {
- ret = update_liodn_stash(info->liodn, dma_domain, val);
+ ret = update_liodn_attr(info->liodn, dma_domain,
+ attr_info);
if (ret)
break;
}
@@ -794,27 +800,92 @@ static int configure_domain_geometry(struct iommu_domain *domain, void *data)
return 0;
}
+/* Set the domain operation mapping attribute */
+static int configure_domain_op_map(struct fsl_dma_domain *dma_domain,
+ void *data)
+{
+ struct dma_window *wnd;
+ unsigned long flags;
+ struct pamu_attr_info attr_info;
+ int ret, i;
+ struct iommu_omi_attribute *omi_attr = data;
+
+ spin_lock_irqsave(&dma_domain->domain_lock, flags);
+
+ if (!dma_domain->win_arr) {
+ pr_err("Number of windows not configured\n");
+ spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
+ return -ENODEV;
+ }
+
+ if (omi_attr->omi >= OMI_MAX) {
+ pr_err("Invalid operation mapping index\n");
+ spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
+ return -EINVAL;
+ }
+
+ if (~omi_attr->window == 0) {
+ wnd = &dma_domain->win_arr[0];
+ for (i = 0; i < dma_domain->win_cnt; i++)
+ wnd[i].omi = omi_attr->omi;
+ } else {
+ wnd = &dma_domain->win_arr[omi_attr->window];
+ wnd->omi = omi_attr->omi;
+ }
+
+ attr_info.window = omi_attr->window;
+ attr_info.field = PAACE_OMI_FIELD;
+ attr_info.value = omi_attr->omi;
+ ret = update_domain_attr(dma_domain, &attr_info);
+
+ spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
+
+ return ret;
+}
+
/* Set the domain stash attribute */
static int configure_domain_stash(struct fsl_dma_domain *dma_domain, void *data)
{
struct iommu_stash_attribute *stash_attr = data;
+ struct dma_window *wnd;
unsigned long flags;
- int ret;
+ u32 stash_id;
+ int ret, i;
+ struct pamu_attr_info attr_info;
spin_lock_irqsave(&dma_domain->domain_lock, flags);
- memcpy(&dma_domain->dma_stash, stash_attr,
- sizeof(struct iommu_stash_attribute));
+ if (!dma_domain->win_arr) {
+ pr_err("Number of windows not configured\n");
+ spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
+ return -ENODEV;
+ }
- dma_domain->stash_id = get_stash_id(stash_attr->cache,
+ stash_id = get_stash_id(stash_attr->cache,
stash_attr->cpu);
- if (dma_domain->stash_id == ~(u32)0) {
+ if (~stash_id == 0) {
pr_err("Invalid stash attributes\n");
spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
return -EINVAL;
}
- ret = update_domain_stash(dma_domain, dma_domain->stash_id);
+ if (~stash_attr->window == 0) {
+ wnd = &dma_domain->win_arr[0];
+ for (i = 0; i < dma_domain->win_cnt; i++) {
+ wnd[i].stash_id = stash_id;
+ memcpy(&wnd[i].stash_attr, stash_attr, sizeof(struct iommu_stash_attribute));
+ wnd[i].stash_attr.window = i;
+ }
+ } else {
+ wnd = &dma_domain->win_arr[stash_attr->window];
+ wnd->stash_id = stash_id;
+ memcpy(&wnd->stash_attr, stash_attr, sizeof(struct iommu_stash_attribute));
+ }
+
+ attr_info.window = stash_attr->window;
+ attr_info.field = PAACE_STASH_FIELD;
+ attr_info.value = stash_id;
+ ret = update_domain_attr(dma_domain, &attr_info);
spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
@@ -869,6 +940,9 @@ static int fsl_pamu_set_domain_attr(struct iommu_domain *domain,
case DOMAIN_ATTR_PAMU_ENABLE:
ret = configure_domain_dma_state(dma_domain, *(int *)data);
break;
+ case DOMAIN_ATTR_PAMU_OP_MAP:
+ ret = configure_domain_op_map(dma_domain, data);
+ break;
default:
pr_err("Unsupported attribute type\n");
ret = -EINVAL;
@@ -886,16 +960,36 @@ static int fsl_pamu_get_domain_attr(struct iommu_domain *domain,
switch (attr_type) {
- case DOMAIN_ATTR_PAMU_STASH:
- memcpy((struct iommu_stash_attribute *) data, &dma_domain->dma_stash,
- sizeof(struct iommu_stash_attribute));
- break;
case DOMAIN_ATTR_PAMU_ENABLE:
*(int *)data = dma_domain->enabled;
break;
case DOMAIN_ATTR_FSL_PAMUV1:
*(int *)data = DOMAIN_ATTR_FSL_PAMUV1;
break;
+ case DOMAIN_ATTR_PAMU_STASH: {
+ struct iommu_stash_attribute *stash_attr = data;
+ struct dma_window *wnd;
+
+ if (stash_attr->window >= dma_domain->win_cnt ||
+ ~stash_attr->window == 0)
+ return -EINVAL;
+
+ wnd = &dma_domain->win_arr[stash_attr->window];
+ memcpy(stash_attr, &wnd->stash_attr, sizeof(struct iommu_stash_attribute));
+ break;
+ }
+ case DOMAIN_ATTR_PAMU_OP_MAP: {
+ struct iommu_omi_attribute *omi_attr = data;
+ struct dma_window *wnd;
+
+ if (omi_attr->window >= dma_domain->win_cnt ||
+ ~omi_attr->window == 0)
+ return -EINVAL;
+
+ wnd = &dma_domain->win_arr[omi_attr->window];
+ omi_attr->omi = wnd->omi;
+ break;
+ }
default:
pr_err("Unsupported attribute type\n");
ret = -EINVAL;
@@ -1058,6 +1152,16 @@ static void fsl_pamu_remove_device(struct device *dev)
iommu_group_remove_device(dev);
}
+static void dma_domain_init_windows(struct fsl_dma_domain *dma_domain)
+{
+ int i;
+
+ for (i = 0; i < dma_domain->win_cnt; i++) {
+ dma_domain->win_arr[i].stash_id = ~(u32)0;
+ dma_domain->win_arr[i].omi = ~(u32)0;
+ }
+}
+
static int fsl_pamu_set_windows(struct iommu_domain *domain, u32 w_count)
{
struct fsl_dma_domain *dma_domain = domain->priv;
@@ -1101,6 +1205,7 @@ static int fsl_pamu_set_windows(struct iommu_domain *domain, u32 w_count)
return -ENOMEM;
}
dma_domain->win_cnt = w_count;
+ dma_domain_init_windows(dma_domain);
}
spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
diff --git a/drivers/iommu/fsl_pamu_domain.h b/drivers/iommu/fsl_pamu_domain.h
index 52dede7..1d55d25 100644
--- a/drivers/iommu/fsl_pamu_domain.h
+++ b/drivers/iommu/fsl_pamu_domain.h
@@ -22,10 +22,13 @@
#include "fsl_pamu.h"
struct dma_window {
- phys_addr_t paddr;
+ phys_addr_t paddr;
u64 size;
- int valid;
- int prot;
+ struct iommu_stash_attribute stash_attr;
+ int valid;
+ int prot;
+ u32 stash_id;
+ u32 omi;
};
struct fsl_dma_domain {
@@ -67,9 +70,6 @@ struct fsl_dma_domain {
*/
int mapped;
int enabled;
- /* stash_id obtained from the stash attribute details */
- u32 stash_id;
- struct iommu_stash_attribute dma_stash;
u32 snoop_id;
struct iommu_domain *iommu_domain;
spinlock_t domain_lock;
diff --git a/drivers/staging/fsl_qbman/qman_driver.c b/drivers/staging/fsl_qbman/qman_driver.c
index d564037..6d879a4 100644
--- a/drivers/staging/fsl_qbman/qman_driver.c
+++ b/drivers/staging/fsl_qbman/qman_driver.c
@@ -488,6 +488,7 @@ static void portal_set_cpu(struct qm_portal_config *pcfg, int cpu)
}
stash_attr.cpu = cpu;
stash_attr.cache = IOMMU_ATTR_CACHE_L1;
+ stash_attr.window = ~(u32)0;
ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_PAMU_STASH,
&stash_attr);
if (ret < 0) {