diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2012-04-12 03:01:49 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@linux.intel.com> | 2012-04-25 05:51:47 -0400 |
commit | affa115ed365d646ad1a8cc7d2d063b8181cce37 (patch) | |
tree | df3d7caa7a0e42228312d6974977e1903306f891 /drivers/dma/amba-pl08x.c | |
parent | d29bf01941795891828bf671f74c3a4f6fc3517f (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.c | 44 |
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 | */ |
99 | struct vendor_data { | 102 | struct 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 | */ |
1484 | static void pl08x_ensure_on(struct pl08x_driver_data *pl08x) | 1488 | static 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 | ||
2043 | static struct vendor_data vendor_nomadik = { | ||
2044 | .channels = 8, | ||
2045 | .dualmaster = true, | ||
2046 | .nomadik = true, | ||
2047 | }; | ||
2048 | |||
2019 | static struct vendor_data vendor_pl081 = { | 2049 | static 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 | }; |