aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2018-09-25 14:16:12 -0400
committerOlof Johansson <olof@lixom.net>2018-09-25 14:16:12 -0400
commitbf1da406909b13903873d1f91346f99303fd8cb3 (patch)
treedc744892ec43a9af5e440e716bde1cdb00e36ccb
parent63c65b872562a2faf8a3a289c117d0c0e3bceb5a (diff)
parentd4983983d98710e4927fdb8de8e987c303b3fba3 (diff)
Merge tag 'amlogic-drivers' of https://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-amlogic into next/drivers
Amlogic ARM64 driver updates for v4.20 - add meson-canvas driver and bindings - firmware: Add serial number sysfs entry * tag 'amlogic-drivers' of https://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-amlogic: soc: amlogic: add meson-canvas driver dt-bindings: soc: amlogic: add meson-canvas documentation firmware: meson_sm: Add serial number sysfs entry Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--Documentation/devicetree/bindings/soc/amlogic/amlogic,canvas.txt29
-rw-r--r--drivers/firmware/meson/meson_sm.c56
-rw-r--r--drivers/soc/amlogic/Kconfig7
-rw-r--r--drivers/soc/amlogic/Makefile1
-rw-r--r--drivers/soc/amlogic/meson-canvas.c185
-rw-r--r--include/linux/firmware/meson/meson_sm.h1
-rw-r--r--include/linux/soc/amlogic/meson-canvas.h65
7 files changed, 344 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/soc/amlogic/amlogic,canvas.txt b/Documentation/devicetree/bindings/soc/amlogic/amlogic,canvas.txt
new file mode 100644
index 000000000000..436d2106e80d
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/amlogic/amlogic,canvas.txt
@@ -0,0 +1,29 @@
1Amlogic Canvas
2================================
3
4A canvas is a collection of metadata that describes a pixel buffer.
5Those metadata include: width, height, phyaddr, wrapping, block mode
6and endianness.
7
8Many IPs within Amlogic SoCs rely on canvas indexes to read/write pixel data
9rather than use the phy addresses directly. For instance, this is the case for
10the video decoders and the display.
11
12Amlogic SoCs have 256 canvas.
13
14Device Tree Bindings:
15---------------------
16
17Video Lookup Table
18--------------------------
19
20Required properties:
21- compatible: "amlogic,canvas"
22- reg: Base physical address and size of the canvas registers.
23
24Example:
25
26canvas: video-lut@48 {
27 compatible = "amlogic,canvas";
28 reg = <0x0 0x48 0x0 0x14>;
29};
diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
index 0ec2ca87318c..29fbc818a573 100644
--- a/drivers/firmware/meson/meson_sm.c
+++ b/drivers/firmware/meson/meson_sm.c
@@ -24,6 +24,7 @@
24#include <linux/printk.h> 24#include <linux/printk.h>
25#include <linux/types.h> 25#include <linux/types.h>
26#include <linux/sizes.h> 26#include <linux/sizes.h>
27 #include <linux/slab.h>
27 28
28#include <linux/firmware/meson/meson_sm.h> 29#include <linux/firmware/meson/meson_sm.h>
29 30
@@ -48,6 +49,7 @@ struct meson_sm_chip gxbb_chip = {
48 CMD(SM_EFUSE_READ, 0x82000030), 49 CMD(SM_EFUSE_READ, 0x82000030),
49 CMD(SM_EFUSE_WRITE, 0x82000031), 50 CMD(SM_EFUSE_WRITE, 0x82000031),
50 CMD(SM_EFUSE_USER_MAX, 0x82000033), 51 CMD(SM_EFUSE_USER_MAX, 0x82000033),
52 CMD(SM_GET_CHIP_ID, 0x82000044),
51 { /* sentinel */ }, 53 { /* sentinel */ },
52 }, 54 },
53}; 55};
@@ -214,6 +216,57 @@ int meson_sm_call_write(void *buffer, unsigned int size, unsigned int cmd_index,
214} 216}
215EXPORT_SYMBOL(meson_sm_call_write); 217EXPORT_SYMBOL(meson_sm_call_write);
216 218
219#define SM_CHIP_ID_LENGTH 119
220#define SM_CHIP_ID_OFFSET 4
221#define SM_CHIP_ID_SIZE 12
222
223static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
224 char *buf)
225{
226 uint8_t *id_buf;
227 int ret;
228
229 id_buf = kmalloc(SM_CHIP_ID_LENGTH, GFP_KERNEL);
230 if (!id_buf)
231 return -ENOMEM;
232
233 ret = meson_sm_call_read(id_buf, SM_CHIP_ID_LENGTH, SM_GET_CHIP_ID,
234 0, 0, 0, 0, 0);
235 if (ret < 0) {
236 kfree(id_buf);
237 return ret;
238 }
239
240 ret = sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
241 id_buf[SM_CHIP_ID_OFFSET + 0],
242 id_buf[SM_CHIP_ID_OFFSET + 1],
243 id_buf[SM_CHIP_ID_OFFSET + 2],
244 id_buf[SM_CHIP_ID_OFFSET + 3],
245 id_buf[SM_CHIP_ID_OFFSET + 4],
246 id_buf[SM_CHIP_ID_OFFSET + 5],
247 id_buf[SM_CHIP_ID_OFFSET + 6],
248 id_buf[SM_CHIP_ID_OFFSET + 7],
249 id_buf[SM_CHIP_ID_OFFSET + 8],
250 id_buf[SM_CHIP_ID_OFFSET + 9],
251 id_buf[SM_CHIP_ID_OFFSET + 10],
252 id_buf[SM_CHIP_ID_OFFSET + 11]);
253
254 kfree(id_buf);
255
256 return ret;
257}
258
259static DEVICE_ATTR_RO(serial);
260
261static struct attribute *meson_sm_sysfs_attributes[] = {
262 &dev_attr_serial.attr,
263 NULL,
264};
265
266static const struct attribute_group meson_sm_sysfs_attr_group = {
267 .attrs = meson_sm_sysfs_attributes,
268};
269
217static const struct of_device_id meson_sm_ids[] = { 270static const struct of_device_id meson_sm_ids[] = {
218 { .compatible = "amlogic,meson-gxbb-sm", .data = &gxbb_chip }, 271 { .compatible = "amlogic,meson-gxbb-sm", .data = &gxbb_chip },
219 { /* sentinel */ }, 272 { /* sentinel */ },
@@ -242,6 +295,9 @@ static int __init meson_sm_probe(struct platform_device *pdev)
242 fw.chip = chip; 295 fw.chip = chip;
243 pr_info("secure-monitor enabled\n"); 296 pr_info("secure-monitor enabled\n");
244 297
298 if (sysfs_create_group(&pdev->dev.kobj, &meson_sm_sysfs_attr_group))
299 goto out_in_base;
300
245 return 0; 301 return 0;
246 302
247out_in_base: 303out_in_base:
diff --git a/drivers/soc/amlogic/Kconfig b/drivers/soc/amlogic/Kconfig
index b04f6e4aedbc..2f282b472912 100644
--- a/drivers/soc/amlogic/Kconfig
+++ b/drivers/soc/amlogic/Kconfig
@@ -1,5 +1,12 @@
1menu "Amlogic SoC drivers" 1menu "Amlogic SoC drivers"
2 2
3config MESON_CANVAS
4 tristate "Amlogic Meson Canvas driver"
5 depends on ARCH_MESON || COMPILE_TEST
6 default n
7 help
8 Say yes to support the canvas IP for Amlogic SoCs.
9
3config MESON_GX_SOCINFO 10config MESON_GX_SOCINFO
4 bool "Amlogic Meson GX SoC Information driver" 11 bool "Amlogic Meson GX SoC Information driver"
5 depends on ARCH_MESON || COMPILE_TEST 12 depends on ARCH_MESON || COMPILE_TEST
diff --git a/drivers/soc/amlogic/Makefile b/drivers/soc/amlogic/Makefile
index 8fa321893928..0ab16d35ac36 100644
--- a/drivers/soc/amlogic/Makefile
+++ b/drivers/soc/amlogic/Makefile
@@ -1,3 +1,4 @@
1obj-$(CONFIG_MESON_CANVAS) += meson-canvas.o
1obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o 2obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o
2obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o 3obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o
3obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o 4obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o
diff --git a/drivers/soc/amlogic/meson-canvas.c b/drivers/soc/amlogic/meson-canvas.c
new file mode 100644
index 000000000000..fce33ca76bb6
--- /dev/null
+++ b/drivers/soc/amlogic/meson-canvas.c
@@ -0,0 +1,185 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018 BayLibre, SAS
4 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
5 * Copyright (C) 2014 Endless Mobile
6 */
7
8#include <linux/kernel.h>
9#include <linux/mfd/syscon.h>
10#include <linux/module.h>
11#include <linux/regmap.h>
12#include <linux/soc/amlogic/meson-canvas.h>
13#include <linux/of_address.h>
14#include <linux/of_platform.h>
15#include <linux/io.h>
16
17#define NUM_CANVAS 256
18
19/* DMC Registers */
20#define DMC_CAV_LUT_DATAL 0x00
21 #define CANVAS_WIDTH_LBIT 29
22 #define CANVAS_WIDTH_LWID 3
23#define DMC_CAV_LUT_DATAH 0x04
24 #define CANVAS_WIDTH_HBIT 0
25 #define CANVAS_HEIGHT_BIT 9
26 #define CANVAS_WRAP_BIT 22
27 #define CANVAS_BLKMODE_BIT 24
28 #define CANVAS_ENDIAN_BIT 26
29#define DMC_CAV_LUT_ADDR 0x08
30 #define CANVAS_LUT_WR_EN BIT(9)
31 #define CANVAS_LUT_RD_EN BIT(8)
32
33struct meson_canvas {
34 struct device *dev;
35 void __iomem *reg_base;
36 spinlock_t lock; /* canvas device lock */
37 u8 used[NUM_CANVAS];
38};
39
40static void canvas_write(struct meson_canvas *canvas, u32 reg, u32 val)
41{
42 writel_relaxed(val, canvas->reg_base + reg);
43}
44
45static u32 canvas_read(struct meson_canvas *canvas, u32 reg)
46{
47 return readl_relaxed(canvas->reg_base + reg);
48}
49
50struct meson_canvas *meson_canvas_get(struct device *dev)
51{
52 struct device_node *canvas_node;
53 struct platform_device *canvas_pdev;
54
55 canvas_node = of_parse_phandle(dev->of_node, "amlogic,canvas", 0);
56 if (!canvas_node)
57 return ERR_PTR(-ENODEV);
58
59 canvas_pdev = of_find_device_by_node(canvas_node);
60 if (!canvas_pdev)
61 return ERR_PTR(-EPROBE_DEFER);
62
63 return dev_get_drvdata(&canvas_pdev->dev);
64}
65EXPORT_SYMBOL_GPL(meson_canvas_get);
66
67int meson_canvas_config(struct meson_canvas *canvas, u8 canvas_index,
68 u32 addr, u32 stride, u32 height,
69 unsigned int wrap,
70 unsigned int blkmode,
71 unsigned int endian)
72{
73 unsigned long flags;
74
75 spin_lock_irqsave(&canvas->lock, flags);
76 if (!canvas->used[canvas_index]) {
77 dev_err(canvas->dev,
78 "Trying to setup non allocated canvas %u\n",
79 canvas_index);
80 spin_unlock_irqrestore(&canvas->lock, flags);
81 return -EINVAL;
82 }
83
84 canvas_write(canvas, DMC_CAV_LUT_DATAL,
85 ((addr + 7) >> 3) |
86 (((stride + 7) >> 3) << CANVAS_WIDTH_LBIT));
87
88 canvas_write(canvas, DMC_CAV_LUT_DATAH,
89 ((((stride + 7) >> 3) >> CANVAS_WIDTH_LWID) <<
90 CANVAS_WIDTH_HBIT) |
91 (height << CANVAS_HEIGHT_BIT) |
92 (wrap << CANVAS_WRAP_BIT) |
93 (blkmode << CANVAS_BLKMODE_BIT) |
94 (endian << CANVAS_ENDIAN_BIT));
95
96 canvas_write(canvas, DMC_CAV_LUT_ADDR,
97 CANVAS_LUT_WR_EN | canvas_index);
98
99 /* Force a read-back to make sure everything is flushed. */
100 canvas_read(canvas, DMC_CAV_LUT_DATAH);
101 spin_unlock_irqrestore(&canvas->lock, flags);
102
103 return 0;
104}
105EXPORT_SYMBOL_GPL(meson_canvas_config);
106
107int meson_canvas_alloc(struct meson_canvas *canvas, u8 *canvas_index)
108{
109 int i;
110 unsigned long flags;
111
112 spin_lock_irqsave(&canvas->lock, flags);
113 for (i = 0; i < NUM_CANVAS; ++i) {
114 if (!canvas->used[i]) {
115 canvas->used[i] = 1;
116 spin_unlock_irqrestore(&canvas->lock, flags);
117 *canvas_index = i;
118 return 0;
119 }
120 }
121 spin_unlock_irqrestore(&canvas->lock, flags);
122
123 dev_err(canvas->dev, "No more canvas available\n");
124 return -ENODEV;
125}
126EXPORT_SYMBOL_GPL(meson_canvas_alloc);
127
128int meson_canvas_free(struct meson_canvas *canvas, u8 canvas_index)
129{
130 unsigned long flags;
131
132 spin_lock_irqsave(&canvas->lock, flags);
133 if (!canvas->used[canvas_index]) {
134 dev_err(canvas->dev,
135 "Trying to free unused canvas %u\n", canvas_index);
136 spin_unlock_irqrestore(&canvas->lock, flags);
137 return -EINVAL;
138 }
139 canvas->used[canvas_index] = 0;
140 spin_unlock_irqrestore(&canvas->lock, flags);
141
142 return 0;
143}
144EXPORT_SYMBOL_GPL(meson_canvas_free);
145
146static int meson_canvas_probe(struct platform_device *pdev)
147{
148 struct resource *res;
149 struct meson_canvas *canvas;
150 struct device *dev = &pdev->dev;
151
152 canvas = devm_kzalloc(dev, sizeof(*canvas), GFP_KERNEL);
153 if (!canvas)
154 return -ENOMEM;
155
156 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
157 canvas->reg_base = devm_ioremap_resource(dev, res);
158 if (IS_ERR(canvas->reg_base))
159 return PTR_ERR(canvas->reg_base);
160
161 canvas->dev = dev;
162 spin_lock_init(&canvas->lock);
163 dev_set_drvdata(dev, canvas);
164
165 return 0;
166}
167
168static const struct of_device_id canvas_dt_match[] = {
169 { .compatible = "amlogic,canvas" },
170 {}
171};
172MODULE_DEVICE_TABLE(of, canvas_dt_match);
173
174static struct platform_driver meson_canvas_driver = {
175 .probe = meson_canvas_probe,
176 .driver = {
177 .name = "amlogic-canvas",
178 .of_match_table = canvas_dt_match,
179 },
180};
181module_platform_driver(meson_canvas_driver);
182
183MODULE_DESCRIPTION("Amlogic Canvas driver");
184MODULE_AUTHOR("Maxime Jourdan <mjourdan@baylibre.com>");
185MODULE_LICENSE("GPL");
diff --git a/include/linux/firmware/meson/meson_sm.h b/include/linux/firmware/meson/meson_sm.h
index 37a5eaea69dd..f98c20dd266e 100644
--- a/include/linux/firmware/meson/meson_sm.h
+++ b/include/linux/firmware/meson/meson_sm.h
@@ -17,6 +17,7 @@ enum {
17 SM_EFUSE_READ, 17 SM_EFUSE_READ,
18 SM_EFUSE_WRITE, 18 SM_EFUSE_WRITE,
19 SM_EFUSE_USER_MAX, 19 SM_EFUSE_USER_MAX,
20 SM_GET_CHIP_ID,
20}; 21};
21 22
22struct meson_sm_firmware; 23struct meson_sm_firmware;
diff --git a/include/linux/soc/amlogic/meson-canvas.h b/include/linux/soc/amlogic/meson-canvas.h
new file mode 100644
index 000000000000..b4dde2fbeb3f
--- /dev/null
+++ b/include/linux/soc/amlogic/meson-canvas.h
@@ -0,0 +1,65 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Copyright (C) 2018 BayLibre, SAS
4 */
5#ifndef __SOC_MESON_CANVAS_H
6#define __SOC_MESON_CANVAS_H
7
8#include <linux/kernel.h>
9
10#define MESON_CANVAS_WRAP_NONE 0x00
11#define MESON_CANVAS_WRAP_X 0x01
12#define MESON_CANVAS_WRAP_Y 0x02
13
14#define MESON_CANVAS_BLKMODE_LINEAR 0x00
15#define MESON_CANVAS_BLKMODE_32x32 0x01
16#define MESON_CANVAS_BLKMODE_64x64 0x02
17
18#define MESON_CANVAS_ENDIAN_SWAP16 0x1
19#define MESON_CANVAS_ENDIAN_SWAP32 0x3
20#define MESON_CANVAS_ENDIAN_SWAP64 0x7
21#define MESON_CANVAS_ENDIAN_SWAP128 0xf
22
23struct meson_canvas;
24
25/**
26 * meson_canvas_get() - get a canvas provider instance
27 *
28 * @dev: consumer device pointer
29 */
30struct meson_canvas *meson_canvas_get(struct device *dev);
31
32/**
33 * meson_canvas_alloc() - take ownership of a canvas
34 *
35 * @canvas: canvas provider instance retrieved from meson_canvas_get()
36 * @canvas_index: will be filled with the canvas ID
37 */
38int meson_canvas_alloc(struct meson_canvas *canvas, u8 *canvas_index);
39
40/**
41 * meson_canvas_free() - remove ownership from a canvas
42 *
43 * @canvas: canvas provider instance retrieved from meson_canvas_get()
44 * @canvas_index: canvas ID that was obtained via meson_canvas_alloc()
45 */
46int meson_canvas_free(struct meson_canvas *canvas, u8 canvas_index);
47
48/**
49 * meson_canvas_config() - configure a canvas
50 *
51 * @canvas: canvas provider instance retrieved from meson_canvas_get()
52 * @canvas_index: canvas ID that was obtained via meson_canvas_alloc()
53 * @addr: physical address to the pixel buffer
54 * @stride: width of the buffer
55 * @height: height of the buffer
56 * @wrap: undocumented
57 * @blkmode: block mode (linear, 32x32, 64x64)
58 * @endian: byte swapping (swap16, swap32, swap64, swap128)
59 */
60int meson_canvas_config(struct meson_canvas *canvas, u8 canvas_index,
61 u32 addr, u32 stride, u32 height,
62 unsigned int wrap, unsigned int blkmode,
63 unsigned int endian);
64
65#endif