aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/amba-pl08x.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2012-04-12 03:01:49 -0400
committerVinod Koul <vinod.koul@linux.intel.com>2012-04-25 05:51:47 -0400
commitaffa115ed365d646ad1a8cc7d2d063b8181cce37 (patch)
treedf3d7caa7a0e42228312d6974977e1903306f891 /drivers/dma/amba-pl08x.c
parentd29bf01941795891828bf671f74c3a4f6fc3517f (diff)
dma/amba-pl08x: add support for the Nomadik variant
The Nomadik PL080 variant has some extra protection bits that may be set, so we need to check these bits to see if the channels are actually available for the DMAengine to use. Cc: Russell King <linux@arm.linux.org.uk> Cc: Alim Akhtar <alim.akhtar@gmail.com> Cc: Alessandro Rubini <rubini@gnudd.com> Reviewed-by: Viresh Kumar <viresh.kumar@st.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Diffstat (limited to 'drivers/dma/amba-pl08x.c')
-rw-r--r--drivers/dma/amba-pl08x.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 08589c683e2b..629250e36d3b 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -95,10 +95,14 @@ static struct amba_driver pl08x_amba_driver;
95 * struct vendor_data - vendor-specific config parameters for PL08x derivatives 95 * struct vendor_data - vendor-specific config parameters for PL08x derivatives
96 * @channels: the number of channels available in this variant 96 * @channels: the number of channels available in this variant
97 * @dualmaster: whether this version supports dual AHB masters or not. 97 * @dualmaster: whether this version supports dual AHB masters or not.
98 * @nomadik: whether the channels have Nomadik security extension bits
99 * that need to be checked for permission before use and some registers are
100 * missing
98 */ 101 */
99struct vendor_data { 102struct vendor_data {
100 u8 channels; 103 u8 channels;
101 bool dualmaster; 104 bool dualmaster;
105 bool nomadik;
102}; 106};
103 107
104/* 108/*
@@ -385,7 +389,7 @@ pl08x_get_phy_channel(struct pl08x_driver_data *pl08x,
385 389
386 spin_lock_irqsave(&ch->lock, flags); 390 spin_lock_irqsave(&ch->lock, flags);
387 391
388 if (!ch->serving) { 392 if (!ch->locked && !ch->serving) {
389 ch->serving = virt_chan; 393 ch->serving = virt_chan;
390 ch->signal = -1; 394 ch->signal = -1;
391 spin_unlock_irqrestore(&ch->lock, flags); 395 spin_unlock_irqrestore(&ch->lock, flags);
@@ -1483,6 +1487,9 @@ bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
1483 */ 1487 */
1484static void pl08x_ensure_on(struct pl08x_driver_data *pl08x) 1488static void pl08x_ensure_on(struct pl08x_driver_data *pl08x)
1485{ 1489{
1490 /* The Nomadik variant does not have the config register */
1491 if (pl08x->vd->nomadik)
1492 return;
1486 writel(PL080_CONFIG_ENABLE, pl08x->base + PL080_CONFIG); 1493 writel(PL080_CONFIG_ENABLE, pl08x->base + PL080_CONFIG);
1487} 1494}
1488 1495
@@ -1772,8 +1779,10 @@ static int pl08x_debugfs_show(struct seq_file *s, void *data)
1772 spin_lock_irqsave(&ch->lock, flags); 1779 spin_lock_irqsave(&ch->lock, flags);
1773 virt_chan = ch->serving; 1780 virt_chan = ch->serving;
1774 1781
1775 seq_printf(s, "%d\t\t%s\n", 1782 seq_printf(s, "%d\t\t%s%s\n",
1776 ch->id, virt_chan ? virt_chan->name : "(none)"); 1783 ch->id,
1784 virt_chan ? virt_chan->name : "(none)",
1785 ch->locked ? " LOCKED" : "");
1777 1786
1778 spin_unlock_irqrestore(&ch->lock, flags); 1787 spin_unlock_irqrestore(&ch->lock, flags);
1779 } 1788 }
@@ -1917,7 +1926,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
1917 } 1926 }
1918 1927
1919 /* Initialize physical channels */ 1928 /* Initialize physical channels */
1920 pl08x->phy_chans = kmalloc((vd->channels * sizeof(*pl08x->phy_chans)), 1929 pl08x->phy_chans = kzalloc((vd->channels * sizeof(*pl08x->phy_chans)),
1921 GFP_KERNEL); 1930 GFP_KERNEL);
1922 if (!pl08x->phy_chans) { 1931 if (!pl08x->phy_chans) {
1923 dev_err(&adev->dev, "%s failed to allocate " 1932 dev_err(&adev->dev, "%s failed to allocate "
@@ -1932,8 +1941,23 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
1932 ch->id = i; 1941 ch->id = i;
1933 ch->base = pl08x->base + PL080_Cx_BASE(i); 1942 ch->base = pl08x->base + PL080_Cx_BASE(i);
1934 spin_lock_init(&ch->lock); 1943 spin_lock_init(&ch->lock);
1935 ch->serving = NULL;
1936 ch->signal = -1; 1944 ch->signal = -1;
1945
1946 /*
1947 * Nomadik variants can have channels that are locked
1948 * down for the secure world only. Lock up these channels
1949 * by perpetually serving a dummy virtual channel.
1950 */
1951 if (vd->nomadik) {
1952 u32 val;
1953
1954 val = readl(ch->base + PL080_CH_CONFIG);
1955 if (val & (PL080N_CONFIG_ITPROT | PL080N_CONFIG_SECPROT)) {
1956 dev_info(&adev->dev, "physical channel %d reserved for secure access only\n", i);
1957 ch->locked = true;
1958 }
1959 }
1960
1937 dev_dbg(&adev->dev, "physical channel %d is %s\n", 1961 dev_dbg(&adev->dev, "physical channel %d is %s\n",
1938 i, pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE"); 1962 i, pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
1939 } 1963 }
@@ -2016,6 +2040,12 @@ static struct vendor_data vendor_pl080 = {
2016 .dualmaster = true, 2040 .dualmaster = true,
2017}; 2041};
2018 2042
2043static struct vendor_data vendor_nomadik = {
2044 .channels = 8,
2045 .dualmaster = true,
2046 .nomadik = true,
2047};
2048
2019static struct vendor_data vendor_pl081 = { 2049static struct vendor_data vendor_pl081 = {
2020 .channels = 2, 2050 .channels = 2,
2021 .dualmaster = false, 2051 .dualmaster = false,
@@ -2036,9 +2066,9 @@ static struct amba_id pl08x_ids[] = {
2036 }, 2066 },
2037 /* Nomadik 8815 PL080 variant */ 2067 /* Nomadik 8815 PL080 variant */
2038 { 2068 {
2039 .id = 0x00280880, 2069 .id = 0x00280080,
2040 .mask = 0x00ffffff, 2070 .mask = 0x00ffffff,
2041 .data = &vendor_pl080, 2071 .data = &vendor_nomadik,
2042 }, 2072 },
2043 { 0, 0 }, 2073 { 0, 0 },
2044}; 2074};