aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/amba-pl08x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/amba-pl08x.c')
-rw-r--r--drivers/dma/amba-pl08x.c192
1 files changed, 189 insertions, 3 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 5de3cf453f35..9b42c0588550 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -83,6 +83,8 @@
83#include <linux/init.h> 83#include <linux/init.h>
84#include <linux/interrupt.h> 84#include <linux/interrupt.h>
85#include <linux/module.h> 85#include <linux/module.h>
86#include <linux/of.h>
87#include <linux/of_dma.h>
86#include <linux/pm_runtime.h> 88#include <linux/pm_runtime.h>
87#include <linux/seq_file.h> 89#include <linux/seq_file.h>
88#include <linux/slab.h> 90#include <linux/slab.h>
@@ -2030,10 +2032,188 @@ static inline void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
2030} 2032}
2031#endif 2033#endif
2032 2034
2035#ifdef CONFIG_OF
2036static struct dma_chan *pl08x_find_chan_id(struct pl08x_driver_data *pl08x,
2037 u32 id)
2038{
2039 struct pl08x_dma_chan *chan;
2040
2041 list_for_each_entry(chan, &pl08x->slave.channels, vc.chan.device_node) {
2042 if (chan->signal == id)
2043 return &chan->vc.chan;
2044 }
2045
2046 return NULL;
2047}
2048
2049static struct dma_chan *pl08x_of_xlate(struct of_phandle_args *dma_spec,
2050 struct of_dma *ofdma)
2051{
2052 struct pl08x_driver_data *pl08x = ofdma->of_dma_data;
2053 struct pl08x_channel_data *data;
2054 struct pl08x_dma_chan *chan;
2055 struct dma_chan *dma_chan;
2056
2057 if (!pl08x)
2058 return NULL;
2059
2060 if (dma_spec->args_count != 2)
2061 return NULL;
2062
2063 dma_chan = pl08x_find_chan_id(pl08x, dma_spec->args[0]);
2064 if (dma_chan)
2065 return dma_get_slave_channel(dma_chan);
2066
2067 chan = devm_kzalloc(pl08x->slave.dev, sizeof(*chan) + sizeof(*data),
2068 GFP_KERNEL);
2069 if (!chan)
2070 return NULL;
2071
2072 data = (void *)&chan[1];
2073 data->bus_id = "(none)";
2074 data->periph_buses = dma_spec->args[1];
2075
2076 chan->cd = data;
2077 chan->host = pl08x;
2078 chan->slave = true;
2079 chan->name = data->bus_id;
2080 chan->state = PL08X_CHAN_IDLE;
2081 chan->signal = dma_spec->args[0];
2082 chan->vc.desc_free = pl08x_desc_free;
2083
2084 vchan_init(&chan->vc, &pl08x->slave);
2085
2086 return dma_get_slave_channel(&chan->vc.chan);
2087}
2088
2089static int pl08x_of_probe(struct amba_device *adev,
2090 struct pl08x_driver_data *pl08x,
2091 struct device_node *np)
2092{
2093 struct pl08x_platform_data *pd;
2094 u32 cctl_memcpy = 0;
2095 u32 val;
2096 int ret;
2097
2098 pd = devm_kzalloc(&adev->dev, sizeof(*pd), GFP_KERNEL);
2099 if (!pd)
2100 return -ENOMEM;
2101
2102 /* Eligible bus masters for fetching LLIs */
2103 if (of_property_read_bool(np, "lli-bus-interface-ahb1"))
2104 pd->lli_buses |= PL08X_AHB1;
2105 if (of_property_read_bool(np, "lli-bus-interface-ahb2"))
2106 pd->lli_buses |= PL08X_AHB2;
2107 if (!pd->lli_buses) {
2108 dev_info(&adev->dev, "no bus masters for LLIs stated, assume all\n");
2109 pd->lli_buses |= PL08X_AHB1 | PL08X_AHB2;
2110 }
2111
2112 /* Eligible bus masters for memory access */
2113 if (of_property_read_bool(np, "mem-bus-interface-ahb1"))
2114 pd->mem_buses |= PL08X_AHB1;
2115 if (of_property_read_bool(np, "mem-bus-interface-ahb2"))
2116 pd->mem_buses |= PL08X_AHB2;
2117 if (!pd->mem_buses) {
2118 dev_info(&adev->dev, "no bus masters for memory stated, assume all\n");
2119 pd->mem_buses |= PL08X_AHB1 | PL08X_AHB2;
2120 }
2121
2122 /* Parse the memcpy channel properties */
2123 ret = of_property_read_u32(np, "memcpy-burst-size", &val);
2124 if (ret) {
2125 dev_info(&adev->dev, "no memcpy burst size specified, using 1 byte\n");
2126 val = 1;
2127 }
2128 switch (val) {
2129 default:
2130 dev_err(&adev->dev, "illegal burst size for memcpy, set to 1\n");
2131 /* Fall through */
2132 case 1:
2133 cctl_memcpy |= PL080_BSIZE_1 << PL080_CONTROL_SB_SIZE_SHIFT |
2134 PL080_BSIZE_1 << PL080_CONTROL_DB_SIZE_SHIFT;
2135 break;
2136 case 4:
2137 cctl_memcpy |= PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
2138 PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT;
2139 break;
2140 case 8:
2141 cctl_memcpy |= PL080_BSIZE_8 << PL080_CONTROL_SB_SIZE_SHIFT |
2142 PL080_BSIZE_8 << PL080_CONTROL_DB_SIZE_SHIFT;
2143 break;
2144 case 16:
2145 cctl_memcpy |= PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT |
2146 PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT;
2147 break;
2148 case 32:
2149 cctl_memcpy |= PL080_BSIZE_32 << PL080_CONTROL_SB_SIZE_SHIFT |
2150 PL080_BSIZE_32 << PL080_CONTROL_DB_SIZE_SHIFT;
2151 break;
2152 case 64:
2153 cctl_memcpy |= PL080_BSIZE_64 << PL080_CONTROL_SB_SIZE_SHIFT |
2154 PL080_BSIZE_64 << PL080_CONTROL_DB_SIZE_SHIFT;
2155 break;
2156 case 128:
2157 cctl_memcpy |= PL080_BSIZE_128 << PL080_CONTROL_SB_SIZE_SHIFT |
2158 PL080_BSIZE_128 << PL080_CONTROL_DB_SIZE_SHIFT;
2159 break;
2160 case 256:
2161 cctl_memcpy |= PL080_BSIZE_256 << PL080_CONTROL_SB_SIZE_SHIFT |
2162 PL080_BSIZE_256 << PL080_CONTROL_DB_SIZE_SHIFT;
2163 break;
2164 }
2165
2166 ret = of_property_read_u32(np, "memcpy-bus-width", &val);
2167 if (ret) {
2168 dev_info(&adev->dev, "no memcpy bus width specified, using 8 bits\n");
2169 val = 8;
2170 }
2171 switch (val) {
2172 default:
2173 dev_err(&adev->dev, "illegal bus width for memcpy, set to 8 bits\n");
2174 /* Fall through */
2175 case 8:
2176 cctl_memcpy |= PL080_WIDTH_8BIT << PL080_CONTROL_SWIDTH_SHIFT |
2177 PL080_WIDTH_8BIT << PL080_CONTROL_DWIDTH_SHIFT;
2178 break;
2179 case 16:
2180 cctl_memcpy |= PL080_WIDTH_16BIT << PL080_CONTROL_SWIDTH_SHIFT |
2181 PL080_WIDTH_16BIT << PL080_CONTROL_DWIDTH_SHIFT;
2182 break;
2183 case 32:
2184 cctl_memcpy |= PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
2185 PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT;
2186 break;
2187 }
2188
2189 /* This is currently the only thing making sense */
2190 cctl_memcpy |= PL080_CONTROL_PROT_SYS;
2191
2192 /* Set up memcpy channel */
2193 pd->memcpy_channel.bus_id = "memcpy";
2194 pd->memcpy_channel.cctl_memcpy = cctl_memcpy;
2195 /* Use the buses that can access memory, obviously */
2196 pd->memcpy_channel.periph_buses = pd->mem_buses;
2197
2198 pl08x->pd = pd;
2199
2200 return of_dma_controller_register(adev->dev.of_node, pl08x_of_xlate,
2201 pl08x);
2202}
2203#else
2204static inline int pl08x_of_probe(struct amba_device *adev,
2205 struct pl08x_driver_data *pl08x,
2206 struct device_node *np)
2207{
2208 return -EINVAL;
2209}
2210#endif
2211
2033static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) 2212static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
2034{ 2213{
2035 struct pl08x_driver_data *pl08x; 2214 struct pl08x_driver_data *pl08x;
2036 const struct vendor_data *vd = id->data; 2215 const struct vendor_data *vd = id->data;
2216 struct device_node *np = adev->dev.of_node;
2037 u32 tsfr_size; 2217 u32 tsfr_size;
2038 int ret = 0; 2218 int ret = 0;
2039 int i; 2219 int i;
@@ -2093,9 +2273,15 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
2093 /* Get the platform data */ 2273 /* Get the platform data */
2094 pl08x->pd = dev_get_platdata(&adev->dev); 2274 pl08x->pd = dev_get_platdata(&adev->dev);
2095 if (!pl08x->pd) { 2275 if (!pl08x->pd) {
2096 dev_err(&adev->dev, "no platform data supplied\n"); 2276 if (np) {
2097 ret = -EINVAL; 2277 ret = pl08x_of_probe(adev, pl08x, np);
2098 goto out_no_platdata; 2278 if (ret)
2279 goto out_no_platdata;
2280 } else {
2281 dev_err(&adev->dev, "no platform data supplied\n");
2282 ret = -EINVAL;
2283 goto out_no_platdata;
2284 }
2099 } 2285 }
2100 2286
2101 /* Assign useful pointers to the driver state */ 2287 /* Assign useful pointers to the driver state */