summaryrefslogtreecommitdiffstats
path: root/drivers/soc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-11 21:19:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-11 21:19:45 -0400
commit8efcf34a263965e471e3999904f94d1f6799d42a (patch)
treea1fe88517cb8a4eb54b50c3ce32eaa1954518b9c /drivers/soc
parent32bcbf8b6d09428907fd045a4ea90562ec7dc4a2 (diff)
parent14321604c82c5415a72e894b83b587a345f5bdf2 (diff)
Merge tag 'armsoc-late' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC late updates from Olof Johansson: "This is a branch with a few merge requests that either came in late, or took a while longer for us to review and merge than usual and thus cut it a bit close to the merge window. We stage them in a separate branch and if things look good, we still send them up -- and that's the case here. This is mostly DT additions for Renesas platforms, adding IP block descriptions for existing and new SoCs. There are also some driver updates for Qualcomm platforms for SMEM/QMI and GENI, which is their generalized serial protocol interface" * tag 'armsoc-late' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (186 commits) soc: qcom: smem: introduce qcom_smem_virt_to_phys() soc: qcom: qmi: fix a buffer sizing bug MAINTAINERS: Update pattern for qcom_scm soc: Unconditionally include qcom Makefile soc: qcom: smem: check sooner in qcom_smem_set_global_partition() soc: qcom: smem: fix qcom_smem_set_global_partition() soc: qcom: smem: fix off-by-one error in qcom_smem_alloc_private() soc: qcom: smem: byte swap values properly soc: qcom: smem: return proper type for cached entry functions soc: qcom: smem: fix first cache entry calculation soc: qcom: cmd-db: Make endian-agnostic drivers: qcom: add command DB driver arm64: dts: renesas: salvator-common: Add ADV7482 support ARM: dts: r8a7740: Add CEU1 ARM: dts: r8a7740: Add CEU0 arm64: dts: renesas: salvator-common: enable VIN arm64: dts: renesas: r8a77970: add VIN and CSI-2 nodes arm64: dts: renesas: r8a77965: add VIN and CSI-2 nodes arm64: dts: renesas: r8a7796: add VIN and CSI-2 nodes arm64: dts: renesas: r8a7795-es1: add CSI-2 node ...
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/Makefile2
-rw-r--r--drivers/soc/qcom/Kconfig18
-rw-r--r--drivers/soc/qcom/Makefile2
-rw-r--r--drivers/soc/qcom/cmd-db.c317
-rw-r--r--drivers/soc/qcom/qcom-geni-se.c748
-rw-r--r--drivers/soc/qcom/qmi_interface.c5
-rw-r--r--drivers/soc/qcom/smd-rpm.c1
-rw-r--r--drivers/soc/qcom/smem.c77
8 files changed, 1145 insertions, 25 deletions
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 40523577bdaa..113e884697fd 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -14,7 +14,7 @@ obj-$(CONFIG_ARCH_MXC) += imx/
14obj-$(CONFIG_SOC_XWAY) += lantiq/ 14obj-$(CONFIG_SOC_XWAY) += lantiq/
15obj-y += mediatek/ 15obj-y += mediatek/
16obj-$(CONFIG_ARCH_MESON) += amlogic/ 16obj-$(CONFIG_ARCH_MESON) += amlogic/
17obj-$(CONFIG_ARCH_QCOM) += qcom/ 17obj-y += qcom/
18obj-y += renesas/ 18obj-y += renesas/
19obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ 19obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
20obj-$(CONFIG_SOC_SAMSUNG) += samsung/ 20obj-$(CONFIG_SOC_SAMSUNG) += samsung/
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index d053f2634c67..9dc02f390ba3 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -3,6 +3,24 @@
3# 3#
4menu "Qualcomm SoC drivers" 4menu "Qualcomm SoC drivers"
5 5
6config QCOM_COMMAND_DB
7 bool "Qualcomm Command DB"
8 depends on (ARCH_QCOM && OF) || COMPILE_TEST
9 help
10 Command DB queries shared memory by key string for shared system
11 resources. Platform drivers that require to set state of a shared
12 resource on a RPM-hardened platform must use this database to get
13 SoC specific identifier and information for the shared resources.
14
15config QCOM_GENI_SE
16 tristate "QCOM GENI Serial Engine Driver"
17 depends on ARCH_QCOM || COMPILE_TEST
18 help
19 This driver is used to manage Generic Interface (GENI) firmware based
20 Qualcomm Technologies, Inc. Universal Peripheral (QUP) Wrapper. This
21 driver is also used to manage the common aspects of multiple Serial
22 Engines present in the QUP.
23
6config QCOM_GLINK_SSR 24config QCOM_GLINK_SSR
7 tristate "Qualcomm Glink SSR driver" 25 tristate "Qualcomm Glink SSR driver"
8 depends on RPMSG 26 depends on RPMSG
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 39de5dee55d9..19dcf957cb3a 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,4 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o
3obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
2obj-$(CONFIG_QCOM_GLINK_SSR) += glink_ssr.o 4obj-$(CONFIG_QCOM_GLINK_SSR) += glink_ssr.o
3obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o 5obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
4obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o 6obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
new file mode 100644
index 000000000000..a6f646295f06
--- /dev/null
+++ b/drivers/soc/qcom/cmd-db.c
@@ -0,0 +1,317 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. */
3
4#include <linux/kernel.h>
5#include <linux/of.h>
6#include <linux/of_address.h>
7#include <linux/of_platform.h>
8#include <linux/of_reserved_mem.h>
9#include <linux/platform_device.h>
10#include <linux/types.h>
11
12#include <soc/qcom/cmd-db.h>
13
14#define NUM_PRIORITY 2
15#define MAX_SLV_ID 8
16#define SLAVE_ID_MASK 0x7
17#define SLAVE_ID_SHIFT 16
18
19/**
20 * struct entry_header: header for each entry in cmddb
21 *
22 * @id: resource's identifier
23 * @priority: unused
24 * @addr: the address of the resource
25 * @len: length of the data
26 * @offset: offset from :@data_offset, start of the data
27 */
28struct entry_header {
29 u8 id[8];
30 __le32 priority[NUM_PRIORITY];
31 __le32 addr;
32 __le16 len;
33 __le16 offset;
34};
35
36/**
37 * struct rsc_hdr: resource header information
38 *
39 * @slv_id: id for the resource
40 * @header_offset: entry's header at offset from the end of the cmd_db_header
41 * @data_offset: entry's data at offset from the end of the cmd_db_header
42 * @cnt: number of entries for HW type
43 * @version: MSB is major, LSB is minor
44 * @reserved: reserved for future use.
45 */
46struct rsc_hdr {
47 __le16 slv_id;
48 __le16 header_offset;
49 __le16 data_offset;
50 __le16 cnt;
51 __le16 version;
52 __le16 reserved[3];
53};
54
55/**
56 * struct cmd_db_header: The DB header information
57 *
58 * @version: The cmd db version
59 * @magic: constant expected in the database
60 * @header: array of resources
61 * @checksum: checksum for the header. Unused.
62 * @reserved: reserved memory
63 * @data: driver specific data
64 */
65struct cmd_db_header {
66 __le32 version;
67 u8 magic[4];
68 struct rsc_hdr header[MAX_SLV_ID];
69 __le32 checksum;
70 __le32 reserved;
71 u8 data[];
72};
73
74/**
75 * DOC: Description of the Command DB database.
76 *
77 * At the start of the command DB memory is the cmd_db_header structure.
78 * The cmd_db_header holds the version, checksum, magic key as well as an
79 * array for header for each slave (depicted by the rsc_header). Each h/w
80 * based accelerator is a 'slave' (shared resource) and has slave id indicating
81 * the type of accelerator. The rsc_header is the header for such individual
82 * slaves of a given type. The entries for each of these slaves begin at the
83 * rsc_hdr.header_offset. In addition each slave could have auxiliary data
84 * that may be needed by the driver. The data for the slave starts at the
85 * entry_header.offset to the location pointed to by the rsc_hdr.data_offset.
86 *
87 * Drivers have a stringified key to a slave/resource. They can query the slave
88 * information and get the slave id and the auxiliary data and the length of the
89 * data. Using this information, they can format the request to be sent to the
90 * h/w accelerator and request a resource state.
91 */
92
93static const u8 CMD_DB_MAGIC[] = { 0xdb, 0x30, 0x03, 0x0c };
94
95static bool cmd_db_magic_matches(const struct cmd_db_header *header)
96{
97 const u8 *magic = header->magic;
98
99 return memcmp(magic, CMD_DB_MAGIC, ARRAY_SIZE(CMD_DB_MAGIC)) == 0;
100}
101
102static struct cmd_db_header *cmd_db_header;
103
104
105static inline void *rsc_to_entry_header(struct rsc_hdr *hdr)
106{
107 u16 offset = le16_to_cpu(hdr->header_offset);
108
109 return cmd_db_header->data + offset;
110}
111
112static inline void *
113rsc_offset(struct rsc_hdr *hdr, struct entry_header *ent)
114{
115 u16 offset = le16_to_cpu(hdr->data_offset);
116 u16 loffset = le16_to_cpu(ent->offset);
117
118 return cmd_db_header->data + offset + loffset;
119}
120
121/**
122 * cmd_db_ready - Indicates if command DB is available
123 *
124 * Return: 0 on success, errno otherwise
125 */
126int cmd_db_ready(void)
127{
128 if (cmd_db_header == NULL)
129 return -EPROBE_DEFER;
130 else if (!cmd_db_magic_matches(cmd_db_header))
131 return -EINVAL;
132
133 return 0;
134}
135EXPORT_SYMBOL(cmd_db_ready);
136
137static int cmd_db_get_header(const char *id, struct entry_header *eh,
138 struct rsc_hdr *rh)
139{
140 struct rsc_hdr *rsc_hdr;
141 struct entry_header *ent;
142 int ret, i, j;
143 u8 query[8];
144
145 ret = cmd_db_ready();
146 if (ret)
147 return ret;
148
149 if (!eh || !rh)
150 return -EINVAL;
151
152 /* Pad out query string to same length as in DB */
153 strncpy(query, id, sizeof(query));
154
155 for (i = 0; i < MAX_SLV_ID; i++) {
156 rsc_hdr = &cmd_db_header->header[i];
157 if (!rsc_hdr->slv_id)
158 break;
159
160 ent = rsc_to_entry_header(rsc_hdr);
161 for (j = 0; j < le16_to_cpu(rsc_hdr->cnt); j++, ent++) {
162 if (memcmp(ent->id, query, sizeof(ent->id)) == 0)
163 break;
164 }
165
166 if (j < le16_to_cpu(rsc_hdr->cnt)) {
167 memcpy(eh, ent, sizeof(*ent));
168 memcpy(rh, rsc_hdr, sizeof(*rh));
169 return 0;
170 }
171 }
172
173 return -ENODEV;
174}
175
176/**
177 * cmd_db_read_addr() - Query command db for resource id address.
178 *
179 * @id: resource id to query for address
180 *
181 * Return: resource address on success, 0 on error
182 *
183 * This is used to retrieve resource address based on resource
184 * id.
185 */
186u32 cmd_db_read_addr(const char *id)
187{
188 int ret;
189 struct entry_header ent;
190 struct rsc_hdr rsc_hdr;
191
192 ret = cmd_db_get_header(id, &ent, &rsc_hdr);
193
194 return ret < 0 ? 0 : le32_to_cpu(ent.addr);
195}
196EXPORT_SYMBOL(cmd_db_read_addr);
197
198/**
199 * cmd_db_read_aux_data() - Query command db for aux data.
200 *
201 * @id: Resource to retrieve AUX Data on.
202 * @data: Data buffer to copy returned aux data to. Returns size on NULL
203 * @len: Caller provides size of data buffer passed in.
204 *
205 * Return: size of data on success, errno otherwise
206 */
207int cmd_db_read_aux_data(const char *id, u8 *data, size_t len)
208{
209 int ret;
210 struct entry_header ent;
211 struct rsc_hdr rsc_hdr;
212 u16 ent_len;
213
214 if (!data)
215 return -EINVAL;
216
217 ret = cmd_db_get_header(id, &ent, &rsc_hdr);
218 if (ret)
219 return ret;
220
221 ent_len = le16_to_cpu(ent.len);
222 if (len < ent_len)
223 return -EINVAL;
224
225 len = min_t(u16, ent_len, len);
226 memcpy(data, rsc_offset(&rsc_hdr, &ent), len);
227
228 return len;
229}
230EXPORT_SYMBOL(cmd_db_read_aux_data);
231
232/**
233 * cmd_db_read_aux_data_len - Get the length of the auxiliary data stored in DB.
234 *
235 * @id: Resource to retrieve AUX Data.
236 *
237 * Return: size on success, 0 on error
238 */
239size_t cmd_db_read_aux_data_len(const char *id)
240{
241 int ret;
242 struct entry_header ent;
243 struct rsc_hdr rsc_hdr;
244
245 ret = cmd_db_get_header(id, &ent, &rsc_hdr);
246
247 return ret < 0 ? 0 : le16_to_cpu(ent.len);
248}
249EXPORT_SYMBOL(cmd_db_read_aux_data_len);
250
251/**
252 * cmd_db_read_slave_id - Get the slave ID for a given resource address
253 *
254 * @id: Resource id to query the DB for version
255 *
256 * Return: cmd_db_hw_type enum on success, CMD_DB_HW_INVALID on error
257 */
258enum cmd_db_hw_type cmd_db_read_slave_id(const char *id)
259{
260 int ret;
261 struct entry_header ent;
262 struct rsc_hdr rsc_hdr;
263 u32 addr;
264
265 ret = cmd_db_get_header(id, &ent, &rsc_hdr);
266 if (ret < 0)
267 return CMD_DB_HW_INVALID;
268
269 addr = le32_to_cpu(ent.addr);
270 return (addr >> SLAVE_ID_SHIFT) & SLAVE_ID_MASK;
271}
272EXPORT_SYMBOL(cmd_db_read_slave_id);
273
274static int cmd_db_dev_probe(struct platform_device *pdev)
275{
276 struct reserved_mem *rmem;
277 int ret = 0;
278
279 rmem = of_reserved_mem_lookup(pdev->dev.of_node);
280 if (!rmem) {
281 dev_err(&pdev->dev, "failed to acquire memory region\n");
282 return -EINVAL;
283 }
284
285 cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WB);
286 if (IS_ERR_OR_NULL(cmd_db_header)) {
287 ret = PTR_ERR(cmd_db_header);
288 cmd_db_header = NULL;
289 return ret;
290 }
291
292 if (!cmd_db_magic_matches(cmd_db_header)) {
293 dev_err(&pdev->dev, "Invalid Command DB Magic\n");
294 return -EINVAL;
295 }
296
297 return 0;
298}
299
300static const struct of_device_id cmd_db_match_table[] = {
301 { .compatible = "qcom,cmd-db" },
302 { },
303};
304
305static struct platform_driver cmd_db_dev_driver = {
306 .probe = cmd_db_dev_probe,
307 .driver = {
308 .name = "cmd-db",
309 .of_match_table = cmd_db_match_table,
310 },
311};
312
313static int __init cmd_db_device_init(void)
314{
315 return platform_driver_register(&cmd_db_dev_driver);
316}
317arch_initcall(cmd_db_device_init);
diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
new file mode 100644
index 000000000000..feed3db21c10
--- /dev/null
+++ b/drivers/soc/qcom/qcom-geni-se.c
@@ -0,0 +1,748 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
3
4#include <linux/clk.h>
5#include <linux/slab.h>
6#include <linux/dma-mapping.h>
7#include <linux/io.h>
8#include <linux/module.h>
9#include <linux/of.h>
10#include <linux/of_platform.h>
11#include <linux/pinctrl/consumer.h>
12#include <linux/platform_device.h>
13#include <linux/qcom-geni-se.h>
14
15/**
16 * DOC: Overview
17 *
18 * Generic Interface (GENI) Serial Engine (SE) Wrapper driver is introduced
19 * to manage GENI firmware based Qualcomm Universal Peripheral (QUP) Wrapper
20 * controller. QUP Wrapper is designed to support various serial bus protocols
21 * like UART, SPI, I2C, I3C, etc.
22 */
23
24/**
25 * DOC: Hardware description
26 *
27 * GENI based QUP is a highly-flexible and programmable module for supporting
28 * a wide range of serial interfaces like UART, SPI, I2C, I3C, etc. A single
29 * QUP module can provide upto 8 serial interfaces, using its internal
30 * serial engines. The actual configuration is determined by the target
31 * platform configuration. The protocol supported by each interface is
32 * determined by the firmware loaded to the serial engine. Each SE consists
33 * of a DMA Engine and GENI sub modules which enable serial engines to
34 * support FIFO and DMA modes of operation.
35 *
36 *
37 * +-----------------------------------------+
38 * |QUP Wrapper |
39 * | +----------------------------+ |
40 * --QUP & SE Clocks--> | Serial Engine N | +-IO------>
41 * | | ... | | Interface
42 * <---Clock Perf.----+ +----+-----------------------+ | |
43 * State Interface | | Serial Engine 1 | | |
44 * | | | | |
45 * | | | | |
46 * <--------AHB-------> | | | |
47 * | | +----+ |
48 * | | | |
49 * | | | |
50 * <------SE IRQ------+ +----------------------------+ |
51 * | |
52 * +-----------------------------------------+
53 *
54 * Figure 1: GENI based QUP Wrapper
55 *
56 * The GENI submodules include primary and secondary sequencers which are
57 * used to drive TX & RX operations. On serial interfaces that operate using
58 * master-slave model, primary sequencer drives both TX & RX operations. On
59 * serial interfaces that operate using peer-to-peer model, primary sequencer
60 * drives TX operation and secondary sequencer drives RX operation.
61 */
62
63/**
64 * DOC: Software description
65 *
66 * GENI SE Wrapper driver is structured into 2 parts:
67 *
68 * geni_wrapper represents QUP Wrapper controller. This part of the driver
69 * manages QUP Wrapper information such as hardware version, clock
70 * performance table that is common to all the internal serial engines.
71 *
72 * geni_se represents serial engine. This part of the driver manages serial
73 * engine information such as clocks, containing QUP Wrapper, etc. This part
74 * of driver also supports operations (eg. initialize the concerned serial
75 * engine, select between FIFO and DMA mode of operation etc.) that are
76 * common to all the serial engines and are independent of serial interfaces.
77 */
78
79#define MAX_CLK_PERF_LEVEL 32
80#define NUM_AHB_CLKS 2
81
82/**
83 * @struct geni_wrapper - Data structure to represent the QUP Wrapper Core
84 * @dev: Device pointer of the QUP wrapper core
85 * @base: Base address of this instance of QUP wrapper core
86 * @ahb_clks: Handle to the primary & secondary AHB clocks
87 */
88struct geni_wrapper {
89 struct device *dev;
90 void __iomem *base;
91 struct clk_bulk_data ahb_clks[NUM_AHB_CLKS];
92};
93
94#define QUP_HW_VER_REG 0x4
95
96/* Common SE registers */
97#define GENI_INIT_CFG_REVISION 0x0
98#define GENI_S_INIT_CFG_REVISION 0x4
99#define GENI_OUTPUT_CTRL 0x24
100#define GENI_CGC_CTRL 0x28
101#define GENI_CLK_CTRL_RO 0x60
102#define GENI_IF_DISABLE_RO 0x64
103#define GENI_FW_S_REVISION_RO 0x6c
104#define SE_GENI_BYTE_GRAN 0x254
105#define SE_GENI_TX_PACKING_CFG0 0x260
106#define SE_GENI_TX_PACKING_CFG1 0x264
107#define SE_GENI_RX_PACKING_CFG0 0x284
108#define SE_GENI_RX_PACKING_CFG1 0x288
109#define SE_GENI_M_GP_LENGTH 0x910
110#define SE_GENI_S_GP_LENGTH 0x914
111#define SE_DMA_TX_PTR_L 0xc30
112#define SE_DMA_TX_PTR_H 0xc34
113#define SE_DMA_TX_ATTR 0xc38
114#define SE_DMA_TX_LEN 0xc3c
115#define SE_DMA_TX_IRQ_EN 0xc48
116#define SE_DMA_TX_IRQ_EN_SET 0xc4c
117#define SE_DMA_TX_IRQ_EN_CLR 0xc50
118#define SE_DMA_TX_LEN_IN 0xc54
119#define SE_DMA_TX_MAX_BURST 0xc5c
120#define SE_DMA_RX_PTR_L 0xd30
121#define SE_DMA_RX_PTR_H 0xd34
122#define SE_DMA_RX_ATTR 0xd38
123#define SE_DMA_RX_LEN 0xd3c
124#define SE_DMA_RX_IRQ_EN 0xd48
125#define SE_DMA_RX_IRQ_EN_SET 0xd4c
126#define SE_DMA_RX_IRQ_EN_CLR 0xd50
127#define SE_DMA_RX_LEN_IN 0xd54
128#define SE_DMA_RX_MAX_BURST 0xd5c
129#define SE_DMA_RX_FLUSH 0xd60
130#define SE_GSI_EVENT_EN 0xe18
131#define SE_IRQ_EN 0xe1c
132#define SE_DMA_GENERAL_CFG 0xe30
133
134/* GENI_OUTPUT_CTRL fields */
135#define DEFAULT_IO_OUTPUT_CTRL_MSK GENMASK(6, 0)
136
137/* GENI_CGC_CTRL fields */
138#define CFG_AHB_CLK_CGC_ON BIT(0)
139#define CFG_AHB_WR_ACLK_CGC_ON BIT(1)
140#define DATA_AHB_CLK_CGC_ON BIT(2)
141#define SCLK_CGC_ON BIT(3)
142#define TX_CLK_CGC_ON BIT(4)
143#define RX_CLK_CGC_ON BIT(5)
144#define EXT_CLK_CGC_ON BIT(6)
145#define PROG_RAM_HCLK_OFF BIT(8)
146#define PROG_RAM_SCLK_OFF BIT(9)
147#define DEFAULT_CGC_EN GENMASK(6, 0)
148
149/* SE_GSI_EVENT_EN fields */
150#define DMA_RX_EVENT_EN BIT(0)
151#define DMA_TX_EVENT_EN BIT(1)
152#define GENI_M_EVENT_EN BIT(2)
153#define GENI_S_EVENT_EN BIT(3)
154
155/* SE_IRQ_EN fields */
156#define DMA_RX_IRQ_EN BIT(0)
157#define DMA_TX_IRQ_EN BIT(1)
158#define GENI_M_IRQ_EN BIT(2)
159#define GENI_S_IRQ_EN BIT(3)
160
161/* SE_DMA_GENERAL_CFG */
162#define DMA_RX_CLK_CGC_ON BIT(0)
163#define DMA_TX_CLK_CGC_ON BIT(1)
164#define DMA_AHB_SLV_CFG_ON BIT(2)
165#define AHB_SEC_SLV_CLK_CGC_ON BIT(3)
166#define DUMMY_RX_NON_BUFFERABLE BIT(4)
167#define RX_DMA_ZERO_PADDING_EN BIT(5)
168#define RX_DMA_IRQ_DELAY_MSK GENMASK(8, 6)
169#define RX_DMA_IRQ_DELAY_SHFT 6
170
171/**
172 * geni_se_get_qup_hw_version() - Read the QUP wrapper Hardware version
173 * @se: Pointer to the corresponding serial engine.
174 *
175 * Return: Hardware Version of the wrapper.
176 */
177u32 geni_se_get_qup_hw_version(struct geni_se *se)
178{
179 struct geni_wrapper *wrapper = se->wrapper;
180
181 return readl_relaxed(wrapper->base + QUP_HW_VER_REG);
182}
183EXPORT_SYMBOL(geni_se_get_qup_hw_version);
184
185static void geni_se_io_set_mode(void __iomem *base)
186{
187 u32 val;
188
189 val = readl_relaxed(base + SE_IRQ_EN);
190 val |= GENI_M_IRQ_EN | GENI_S_IRQ_EN;
191 val |= DMA_TX_IRQ_EN | DMA_RX_IRQ_EN;
192 writel_relaxed(val, base + SE_IRQ_EN);
193
194 val = readl_relaxed(base + SE_GENI_DMA_MODE_EN);
195 val &= ~GENI_DMA_MODE_EN;
196 writel_relaxed(val, base + SE_GENI_DMA_MODE_EN);
197
198 writel_relaxed(0, base + SE_GSI_EVENT_EN);
199}
200
201static void geni_se_io_init(void __iomem *base)
202{
203 u32 val;
204
205 val = readl_relaxed(base + GENI_CGC_CTRL);
206 val |= DEFAULT_CGC_EN;
207 writel_relaxed(val, base + GENI_CGC_CTRL);
208
209 val = readl_relaxed(base + SE_DMA_GENERAL_CFG);
210 val |= AHB_SEC_SLV_CLK_CGC_ON | DMA_AHB_SLV_CFG_ON;
211 val |= DMA_TX_CLK_CGC_ON | DMA_RX_CLK_CGC_ON;
212 writel_relaxed(val, base + SE_DMA_GENERAL_CFG);
213
214 writel_relaxed(DEFAULT_IO_OUTPUT_CTRL_MSK, base + GENI_OUTPUT_CTRL);
215 writel_relaxed(FORCE_DEFAULT, base + GENI_FORCE_DEFAULT_REG);
216}
217
218/**
219 * geni_se_init() - Initialize the GENI serial engine
220 * @se: Pointer to the concerned serial engine.
221 * @rx_wm: Receive watermark, in units of FIFO words.
222 * @rx_rfr_wm: Ready-for-receive watermark, in units of FIFO words.
223 *
224 * This function is used to initialize the GENI serial engine, configure
225 * receive watermark and ready-for-receive watermarks.
226 */
227void geni_se_init(struct geni_se *se, u32 rx_wm, u32 rx_rfr)
228{
229 u32 val;
230
231 geni_se_io_init(se->base);
232 geni_se_io_set_mode(se->base);
233
234 writel_relaxed(rx_wm, se->base + SE_GENI_RX_WATERMARK_REG);
235 writel_relaxed(rx_rfr, se->base + SE_GENI_RX_RFR_WATERMARK_REG);
236
237 val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
238 val |= M_COMMON_GENI_M_IRQ_EN;
239 writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
240
241 val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
242 val |= S_COMMON_GENI_S_IRQ_EN;
243 writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
244}
245EXPORT_SYMBOL(geni_se_init);
246
247static void geni_se_select_fifo_mode(struct geni_se *se)
248{
249 u32 proto = geni_se_read_proto(se);
250 u32 val;
251
252 writel_relaxed(0, se->base + SE_GSI_EVENT_EN);
253 writel_relaxed(0xffffffff, se->base + SE_GENI_M_IRQ_CLEAR);
254 writel_relaxed(0xffffffff, se->base + SE_GENI_S_IRQ_CLEAR);
255 writel_relaxed(0xffffffff, se->base + SE_DMA_TX_IRQ_CLR);
256 writel_relaxed(0xffffffff, se->base + SE_DMA_RX_IRQ_CLR);
257 writel_relaxed(0xffffffff, se->base + SE_IRQ_EN);
258
259 val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
260 if (proto != GENI_SE_UART) {
261 val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN;
262 val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
263 }
264 writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
265
266 val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
267 if (proto != GENI_SE_UART)
268 val |= S_CMD_DONE_EN;
269 writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
270
271 val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
272 val &= ~GENI_DMA_MODE_EN;
273 writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN);
274}
275
276static void geni_se_select_dma_mode(struct geni_se *se)
277{
278 u32 val;
279
280 writel_relaxed(0, se->base + SE_GSI_EVENT_EN);
281 writel_relaxed(0xffffffff, se->base + SE_GENI_M_IRQ_CLEAR);
282 writel_relaxed(0xffffffff, se->base + SE_GENI_S_IRQ_CLEAR);
283 writel_relaxed(0xffffffff, se->base + SE_DMA_TX_IRQ_CLR);
284 writel_relaxed(0xffffffff, se->base + SE_DMA_RX_IRQ_CLR);
285 writel_relaxed(0xffffffff, se->base + SE_IRQ_EN);
286
287 val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
288 val |= GENI_DMA_MODE_EN;
289 writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN);
290}
291
292/**
293 * geni_se_select_mode() - Select the serial engine transfer mode
294 * @se: Pointer to the concerned serial engine.
295 * @mode: Transfer mode to be selected.
296 */
297void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode)
298{
299 WARN_ON(mode != GENI_SE_FIFO && mode != GENI_SE_DMA);
300
301 switch (mode) {
302 case GENI_SE_FIFO:
303 geni_se_select_fifo_mode(se);
304 break;
305 case GENI_SE_DMA:
306 geni_se_select_dma_mode(se);
307 break;
308 case GENI_SE_INVALID:
309 default:
310 break;
311 }
312}
313EXPORT_SYMBOL(geni_se_select_mode);
314
315/**
316 * DOC: Overview
317 *
318 * GENI FIFO packing is highly configurable. TX/RX packing/unpacking consist
319 * of up to 4 operations, each operation represented by 4 configuration vectors
320 * of 10 bits programmed in GENI_TX_PACKING_CFG0 and GENI_TX_PACKING_CFG1 for
321 * TX FIFO and in GENI_RX_PACKING_CFG0 and GENI_RX_PACKING_CFG1 for RX FIFO.
322 * Refer to below examples for detailed bit-field description.
323 *
324 * Example 1: word_size = 7, packing_mode = 4 x 8, msb_to_lsb = 1
325 *
326 * +-----------+-------+-------+-------+-------+
327 * | | vec_0 | vec_1 | vec_2 | vec_3 |
328 * +-----------+-------+-------+-------+-------+
329 * | start | 0x6 | 0xe | 0x16 | 0x1e |
330 * | direction | 1 | 1 | 1 | 1 |
331 * | length | 6 | 6 | 6 | 6 |
332 * | stop | 0 | 0 | 0 | 1 |
333 * +-----------+-------+-------+-------+-------+
334 *
335 * Example 2: word_size = 15, packing_mode = 2 x 16, msb_to_lsb = 0
336 *
337 * +-----------+-------+-------+-------+-------+
338 * | | vec_0 | vec_1 | vec_2 | vec_3 |
339 * +-----------+-------+-------+-------+-------+
340 * | start | 0x0 | 0x8 | 0x10 | 0x18 |
341 * | direction | 0 | 0 | 0 | 0 |
342 * | length | 7 | 6 | 7 | 6 |
343 * | stop | 0 | 0 | 0 | 1 |
344 * +-----------+-------+-------+-------+-------+
345 *
346 * Example 3: word_size = 23, packing_mode = 1 x 32, msb_to_lsb = 1
347 *
348 * +-----------+-------+-------+-------+-------+
349 * | | vec_0 | vec_1 | vec_2 | vec_3 |
350 * +-----------+-------+-------+-------+-------+
351 * | start | 0x16 | 0xe | 0x6 | 0x0 |
352 * | direction | 1 | 1 | 1 | 1 |
353 * | length | 7 | 7 | 6 | 0 |
354 * | stop | 0 | 0 | 1 | 0 |
355 * +-----------+-------+-------+-------+-------+
356 *
357 */
358
359#define NUM_PACKING_VECTORS 4
360#define PACKING_START_SHIFT 5
361#define PACKING_DIR_SHIFT 4
362#define PACKING_LEN_SHIFT 1
363#define PACKING_STOP_BIT BIT(0)
364#define PACKING_VECTOR_SHIFT 10
365/**
366 * geni_se_config_packing() - Packing configuration of the serial engine
367 * @se: Pointer to the concerned serial engine
368 * @bpw: Bits of data per transfer word.
369 * @pack_words: Number of words per fifo element.
370 * @msb_to_lsb: Transfer from MSB to LSB or vice-versa.
371 * @tx_cfg: Flag to configure the TX Packing.
372 * @rx_cfg: Flag to configure the RX Packing.
373 *
374 * This function is used to configure the packing rules for the current
375 * transfer.
376 */
377void geni_se_config_packing(struct geni_se *se, int bpw, int pack_words,
378 bool msb_to_lsb, bool tx_cfg, bool rx_cfg)
379{
380 u32 cfg0, cfg1, cfg[NUM_PACKING_VECTORS] = {0};
381 int len;
382 int temp_bpw = bpw;
383 int idx_start = msb_to_lsb ? bpw - 1 : 0;
384 int idx = idx_start;
385 int idx_delta = msb_to_lsb ? -BITS_PER_BYTE : BITS_PER_BYTE;
386 int ceil_bpw = ALIGN(bpw, BITS_PER_BYTE);
387 int iter = (ceil_bpw * pack_words) / BITS_PER_BYTE;
388 int i;
389
390 if (iter <= 0 || iter > NUM_PACKING_VECTORS)
391 return;
392
393 for (i = 0; i < iter; i++) {
394 len = min_t(int, temp_bpw, BITS_PER_BYTE) - 1;
395 cfg[i] = idx << PACKING_START_SHIFT;
396 cfg[i] |= msb_to_lsb << PACKING_DIR_SHIFT;
397 cfg[i] |= len << PACKING_LEN_SHIFT;
398
399 if (temp_bpw <= BITS_PER_BYTE) {
400 idx = ((i + 1) * BITS_PER_BYTE) + idx_start;
401 temp_bpw = bpw;
402 } else {
403 idx = idx + idx_delta;
404 temp_bpw = temp_bpw - BITS_PER_BYTE;
405 }
406 }
407 cfg[iter - 1] |= PACKING_STOP_BIT;
408 cfg0 = cfg[0] | (cfg[1] << PACKING_VECTOR_SHIFT);
409 cfg1 = cfg[2] | (cfg[3] << PACKING_VECTOR_SHIFT);
410
411 if (tx_cfg) {
412 writel_relaxed(cfg0, se->base + SE_GENI_TX_PACKING_CFG0);
413 writel_relaxed(cfg1, se->base + SE_GENI_TX_PACKING_CFG1);
414 }
415 if (rx_cfg) {
416 writel_relaxed(cfg0, se->base + SE_GENI_RX_PACKING_CFG0);
417 writel_relaxed(cfg1, se->base + SE_GENI_RX_PACKING_CFG1);
418 }
419
420 /*
421 * Number of protocol words in each FIFO entry
422 * 0 - 4x8, four words in each entry, max word size of 8 bits
423 * 1 - 2x16, two words in each entry, max word size of 16 bits
424 * 2 - 1x32, one word in each entry, max word size of 32 bits
425 * 3 - undefined
426 */
427 if (pack_words || bpw == 32)
428 writel_relaxed(bpw / 16, se->base + SE_GENI_BYTE_GRAN);
429}
430EXPORT_SYMBOL(geni_se_config_packing);
431
432static void geni_se_clks_off(struct geni_se *se)
433{
434 struct geni_wrapper *wrapper = se->wrapper;
435
436 clk_disable_unprepare(se->clk);
437 clk_bulk_disable_unprepare(ARRAY_SIZE(wrapper->ahb_clks),
438 wrapper->ahb_clks);
439}
440
441/**
442 * geni_se_resources_off() - Turn off resources associated with the serial
443 * engine
444 * @se: Pointer to the concerned serial engine.
445 *
446 * Return: 0 on success, standard Linux error codes on failure/error.
447 */
448int geni_se_resources_off(struct geni_se *se)
449{
450 int ret;
451
452 ret = pinctrl_pm_select_sleep_state(se->dev);
453 if (ret)
454 return ret;
455
456 geni_se_clks_off(se);
457 return 0;
458}
459EXPORT_SYMBOL(geni_se_resources_off);
460
461static int geni_se_clks_on(struct geni_se *se)
462{
463 int ret;
464 struct geni_wrapper *wrapper = se->wrapper;
465
466 ret = clk_bulk_prepare_enable(ARRAY_SIZE(wrapper->ahb_clks),
467 wrapper->ahb_clks);
468 if (ret)
469 return ret;
470
471 ret = clk_prepare_enable(se->clk);
472 if (ret)
473 clk_bulk_disable_unprepare(ARRAY_SIZE(wrapper->ahb_clks),
474 wrapper->ahb_clks);
475 return ret;
476}
477
478/**
479 * geni_se_resources_on() - Turn on resources associated with the serial
480 * engine
481 * @se: Pointer to the concerned serial engine.
482 *
483 * Return: 0 on success, standard Linux error codes on failure/error.
484 */
485int geni_se_resources_on(struct geni_se *se)
486{
487 int ret;
488
489 ret = geni_se_clks_on(se);
490 if (ret)
491 return ret;
492
493 ret = pinctrl_pm_select_default_state(se->dev);
494 if (ret)
495 geni_se_clks_off(se);
496
497 return ret;
498}
499EXPORT_SYMBOL(geni_se_resources_on);
500
501/**
502 * geni_se_clk_tbl_get() - Get the clock table to program DFS
503 * @se: Pointer to the concerned serial engine.
504 * @tbl: Table in which the output is returned.
505 *
506 * This function is called by the protocol drivers to determine the different
507 * clock frequencies supported by serial engine core clock. The protocol
508 * drivers use the output to determine the clock frequency index to be
509 * programmed into DFS.
510 *
511 * Return: number of valid performance levels in the table on success,
512 * standard Linux error codes on failure.
513 */
514int geni_se_clk_tbl_get(struct geni_se *se, unsigned long **tbl)
515{
516 unsigned long freq = 0;
517 int i;
518
519 if (se->clk_perf_tbl) {
520 *tbl = se->clk_perf_tbl;
521 return se->num_clk_levels;
522 }
523
524 se->clk_perf_tbl = devm_kcalloc(se->dev, MAX_CLK_PERF_LEVEL,
525 sizeof(*se->clk_perf_tbl),
526 GFP_KERNEL);
527 if (!se->clk_perf_tbl)
528 return -ENOMEM;
529
530 for (i = 0; i < MAX_CLK_PERF_LEVEL; i++) {
531 freq = clk_round_rate(se->clk, freq + 1);
532 if (!freq || freq == se->clk_perf_tbl[i - 1])
533 break;
534 se->clk_perf_tbl[i] = freq;
535 }
536 se->num_clk_levels = i;
537 *tbl = se->clk_perf_tbl;
538 return se->num_clk_levels;
539}
540EXPORT_SYMBOL(geni_se_clk_tbl_get);
541
542/**
543 * geni_se_clk_freq_match() - Get the matching or closest SE clock frequency
544 * @se: Pointer to the concerned serial engine.
545 * @req_freq: Requested clock frequency.
546 * @index: Index of the resultant frequency in the table.
547 * @res_freq: Resultant frequency which matches or is closer to the
548 * requested frequency.
549 * @exact: Flag to indicate exact multiple requirement of the requested
550 * frequency.
551 *
552 * This function is called by the protocol drivers to determine the matching
553 * or exact multiple of the requested frequency, as provided by the serial
554 * engine clock in order to meet the performance requirements. If there is
555 * no matching or exact multiple of the requested frequency found, then it
556 * selects the closest floor frequency, if exact flag is not set.
557 *
558 * Return: 0 on success, standard Linux error codes on failure.
559 */
560int geni_se_clk_freq_match(struct geni_se *se, unsigned long req_freq,
561 unsigned int *index, unsigned long *res_freq,
562 bool exact)
563{
564 unsigned long *tbl;
565 int num_clk_levels;
566 int i;
567
568 num_clk_levels = geni_se_clk_tbl_get(se, &tbl);
569 if (num_clk_levels < 0)
570 return num_clk_levels;
571
572 if (num_clk_levels == 0)
573 return -EINVAL;
574
575 *res_freq = 0;
576 for (i = 0; i < num_clk_levels; i++) {
577 if (!(tbl[i] % req_freq)) {
578 *index = i;
579 *res_freq = tbl[i];
580 return 0;
581 }
582
583 if (!(*res_freq) || ((tbl[i] > *res_freq) &&
584 (tbl[i] < req_freq))) {
585 *index = i;
586 *res_freq = tbl[i];
587 }
588 }
589
590 if (exact)
591 return -EINVAL;
592
593 return 0;
594}
595EXPORT_SYMBOL(geni_se_clk_freq_match);
596
597#define GENI_SE_DMA_DONE_EN BIT(0)
598#define GENI_SE_DMA_EOT_EN BIT(1)
599#define GENI_SE_DMA_AHB_ERR_EN BIT(2)
600#define GENI_SE_DMA_EOT_BUF BIT(0)
601/**
602 * geni_se_tx_dma_prep() - Prepare the serial engine for TX DMA transfer
603 * @se: Pointer to the concerned serial engine.
604 * @buf: Pointer to the TX buffer.
605 * @len: Length of the TX buffer.
606 * @iova: Pointer to store the mapped DMA address.
607 *
608 * This function is used to prepare the buffers for DMA TX.
609 *
610 * Return: 0 on success, standard Linux error codes on failure.
611 */
612int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len,
613 dma_addr_t *iova)
614{
615 struct geni_wrapper *wrapper = se->wrapper;
616 u32 val;
617
618 *iova = dma_map_single(wrapper->dev, buf, len, DMA_TO_DEVICE);
619 if (dma_mapping_error(wrapper->dev, *iova))
620 return -EIO;
621
622 val = GENI_SE_DMA_DONE_EN;
623 val |= GENI_SE_DMA_EOT_EN;
624 val |= GENI_SE_DMA_AHB_ERR_EN;
625 writel_relaxed(val, se->base + SE_DMA_TX_IRQ_EN_SET);
626 writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_TX_PTR_L);
627 writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_TX_PTR_H);
628 writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR);
629 writel_relaxed(len, se->base + SE_DMA_TX_LEN);
630 return 0;
631}
632EXPORT_SYMBOL(geni_se_tx_dma_prep);
633
634/**
635 * geni_se_rx_dma_prep() - Prepare the serial engine for RX DMA transfer
636 * @se: Pointer to the concerned serial engine.
637 * @buf: Pointer to the RX buffer.
638 * @len: Length of the RX buffer.
639 * @iova: Pointer to store the mapped DMA address.
640 *
641 * This function is used to prepare the buffers for DMA RX.
642 *
643 * Return: 0 on success, standard Linux error codes on failure.
644 */
645int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
646 dma_addr_t *iova)
647{
648 struct geni_wrapper *wrapper = se->wrapper;
649 u32 val;
650
651 *iova = dma_map_single(wrapper->dev, buf, len, DMA_FROM_DEVICE);
652 if (dma_mapping_error(wrapper->dev, *iova))
653 return -EIO;
654
655 val = GENI_SE_DMA_DONE_EN;
656 val |= GENI_SE_DMA_EOT_EN;
657 val |= GENI_SE_DMA_AHB_ERR_EN;
658 writel_relaxed(val, se->base + SE_DMA_RX_IRQ_EN_SET);
659 writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_RX_PTR_L);
660 writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_RX_PTR_H);
661 /* RX does not have EOT buffer type bit. So just reset RX_ATTR */
662 writel_relaxed(0, se->base + SE_DMA_RX_ATTR);
663 writel_relaxed(len, se->base + SE_DMA_RX_LEN);
664 return 0;
665}
666EXPORT_SYMBOL(geni_se_rx_dma_prep);
667
668/**
669 * geni_se_tx_dma_unprep() - Unprepare the serial engine after TX DMA transfer
670 * @se: Pointer to the concerned serial engine.
671 * @iova: DMA address of the TX buffer.
672 * @len: Length of the TX buffer.
673 *
674 * This function is used to unprepare the DMA buffers after DMA TX.
675 */
676void geni_se_tx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
677{
678 struct geni_wrapper *wrapper = se->wrapper;
679
680 if (iova && !dma_mapping_error(wrapper->dev, iova))
681 dma_unmap_single(wrapper->dev, iova, len, DMA_TO_DEVICE);
682}
683EXPORT_SYMBOL(geni_se_tx_dma_unprep);
684
685/**
686 * geni_se_rx_dma_unprep() - Unprepare the serial engine after RX DMA transfer
687 * @se: Pointer to the concerned serial engine.
688 * @iova: DMA address of the RX buffer.
689 * @len: Length of the RX buffer.
690 *
691 * This function is used to unprepare the DMA buffers after DMA RX.
692 */
693void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
694{
695 struct geni_wrapper *wrapper = se->wrapper;
696
697 if (iova && !dma_mapping_error(wrapper->dev, iova))
698 dma_unmap_single(wrapper->dev, iova, len, DMA_FROM_DEVICE);
699}
700EXPORT_SYMBOL(geni_se_rx_dma_unprep);
701
702static int geni_se_probe(struct platform_device *pdev)
703{
704 struct device *dev = &pdev->dev;
705 struct resource *res;
706 struct geni_wrapper *wrapper;
707 int ret;
708
709 wrapper = devm_kzalloc(dev, sizeof(*wrapper), GFP_KERNEL);
710 if (!wrapper)
711 return -ENOMEM;
712
713 wrapper->dev = dev;
714 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
715 wrapper->base = devm_ioremap_resource(dev, res);
716 if (IS_ERR(wrapper->base))
717 return PTR_ERR(wrapper->base);
718
719 wrapper->ahb_clks[0].id = "m-ahb";
720 wrapper->ahb_clks[1].id = "s-ahb";
721 ret = devm_clk_bulk_get(dev, NUM_AHB_CLKS, wrapper->ahb_clks);
722 if (ret) {
723 dev_err(dev, "Err getting AHB clks %d\n", ret);
724 return ret;
725 }
726
727 dev_set_drvdata(dev, wrapper);
728 dev_dbg(dev, "GENI SE Driver probed\n");
729 return devm_of_platform_populate(dev);
730}
731
732static const struct of_device_id geni_se_dt_match[] = {
733 { .compatible = "qcom,geni-se-qup", },
734 {}
735};
736MODULE_DEVICE_TABLE(of, geni_se_dt_match);
737
738static struct platform_driver geni_se_driver = {
739 .driver = {
740 .name = "geni_se_qup",
741 .of_match_table = geni_se_dt_match,
742 },
743 .probe = geni_se_probe,
744};
745module_platform_driver(geni_se_driver);
746
747MODULE_DESCRIPTION("GENI Serial Engine Driver");
748MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c
index 321982277697..938ca41c56cd 100644
--- a/drivers/soc/qcom/qmi_interface.c
+++ b/drivers/soc/qcom/qmi_interface.c
@@ -639,10 +639,11 @@ int qmi_handle_init(struct qmi_handle *qmi, size_t recv_buf_size,
639 if (ops) 639 if (ops)
640 qmi->ops = *ops; 640 qmi->ops = *ops;
641 641
642 /* Make room for the header */
643 recv_buf_size += sizeof(struct qmi_header);
644 /* Must also be sufficient to hold a control packet */
642 if (recv_buf_size < sizeof(struct qrtr_ctrl_pkt)) 645 if (recv_buf_size < sizeof(struct qrtr_ctrl_pkt))
643 recv_buf_size = sizeof(struct qrtr_ctrl_pkt); 646 recv_buf_size = sizeof(struct qrtr_ctrl_pkt);
644 else
645 recv_buf_size += sizeof(struct qmi_header);
646 647
647 qmi->recv_buf_size = recv_buf_size; 648 qmi->recv_buf_size = recv_buf_size;
648 qmi->recv_buf = kzalloc(recv_buf_size, GFP_KERNEL); 649 qmi->recv_buf = kzalloc(recv_buf_size, GFP_KERNEL);
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index c2346752b3ea..93517ed83355 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -226,6 +226,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = {
226 { .compatible = "qcom,rpm-msm8916" }, 226 { .compatible = "qcom,rpm-msm8916" },
227 { .compatible = "qcom,rpm-msm8974" }, 227 { .compatible = "qcom,rpm-msm8974" },
228 { .compatible = "qcom,rpm-msm8996" }, 228 { .compatible = "qcom,rpm-msm8996" },
229 { .compatible = "qcom,rpm-msm8998" },
229 {} 230 {}
230}; 231};
231MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match); 232MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match);
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 0b94d62fad2b..70b2ee80d6bd 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -280,7 +280,7 @@ struct qcom_smem {
280 struct smem_region regions[0]; 280 struct smem_region regions[0];
281}; 281};
282 282
283static struct smem_private_entry * 283static void *
284phdr_to_last_uncached_entry(struct smem_partition_header *phdr) 284phdr_to_last_uncached_entry(struct smem_partition_header *phdr)
285{ 285{
286 void *p = phdr; 286 void *p = phdr;
@@ -288,15 +288,18 @@ phdr_to_last_uncached_entry(struct smem_partition_header *phdr)
288 return p + le32_to_cpu(phdr->offset_free_uncached); 288 return p + le32_to_cpu(phdr->offset_free_uncached);
289} 289}
290 290
291static void *phdr_to_first_cached_entry(struct smem_partition_header *phdr, 291static struct smem_private_entry *
292phdr_to_first_cached_entry(struct smem_partition_header *phdr,
292 size_t cacheline) 293 size_t cacheline)
293{ 294{
294 void *p = phdr; 295 void *p = phdr;
296 struct smem_private_entry *e;
295 297
296 return p + le32_to_cpu(phdr->size) - ALIGN(sizeof(*phdr), cacheline); 298 return p + le32_to_cpu(phdr->size) - ALIGN(sizeof(*e), cacheline);
297} 299}
298 300
299static void *phdr_to_last_cached_entry(struct smem_partition_header *phdr) 301static void *
302phdr_to_last_cached_entry(struct smem_partition_header *phdr)
300{ 303{
301 void *p = phdr; 304 void *p = phdr;
302 305
@@ -361,14 +364,14 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
361 end = phdr_to_last_uncached_entry(phdr); 364 end = phdr_to_last_uncached_entry(phdr);
362 cached = phdr_to_last_cached_entry(phdr); 365 cached = phdr_to_last_cached_entry(phdr);
363 366
364 while (hdr < end) { 367 if (smem->global_partition) {
365 if (hdr->canary != SMEM_PRIVATE_CANARY) { 368 dev_err(smem->dev, "Already found the global partition\n");
366 dev_err(smem->dev, 369 return -EINVAL;
367 "Found invalid canary in hosts %d:%d partition\n", 370 }
368 phdr->host0, phdr->host1);
369 return -EINVAL;
370 }
371 371
372 while (hdr < end) {
373 if (hdr->canary != SMEM_PRIVATE_CANARY)
374 goto bad_canary;
372 if (le16_to_cpu(hdr->item) == item) 375 if (le16_to_cpu(hdr->item) == item)
373 return -EEXIST; 376 return -EEXIST;
374 377
@@ -377,7 +380,7 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
377 380
378 /* Check that we don't grow into the cached region */ 381 /* Check that we don't grow into the cached region */
379 alloc_size = sizeof(*hdr) + ALIGN(size, 8); 382 alloc_size = sizeof(*hdr) + ALIGN(size, 8);
380 if ((void *)hdr + alloc_size >= cached) { 383 if ((void *)hdr + alloc_size > cached) {
381 dev_err(smem->dev, "Out of memory\n"); 384 dev_err(smem->dev, "Out of memory\n");
382 return -ENOSPC; 385 return -ENOSPC;
383 } 386 }
@@ -397,6 +400,11 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
397 le32_add_cpu(&phdr->offset_free_uncached, alloc_size); 400 le32_add_cpu(&phdr->offset_free_uncached, alloc_size);
398 401
399 return 0; 402 return 0;
403bad_canary:
404 dev_err(smem->dev, "Found invalid canary in hosts %hu:%hu partition\n",
405 le16_to_cpu(phdr->host0), le16_to_cpu(phdr->host1));
406
407 return -EINVAL;
400} 408}
401 409
402static int qcom_smem_alloc_global(struct qcom_smem *smem, 410static int qcom_smem_alloc_global(struct qcom_smem *smem,
@@ -560,8 +568,8 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
560 return ERR_PTR(-ENOENT); 568 return ERR_PTR(-ENOENT);
561 569
562invalid_canary: 570invalid_canary:
563 dev_err(smem->dev, "Found invalid canary in hosts %d:%d partition\n", 571 dev_err(smem->dev, "Found invalid canary in hosts %hu:%hu partition\n",
564 phdr->host0, phdr->host1); 572 le16_to_cpu(phdr->host0), le16_to_cpu(phdr->host1));
565 573
566 return ERR_PTR(-EINVAL); 574 return ERR_PTR(-EINVAL);
567} 575}
@@ -647,6 +655,33 @@ int qcom_smem_get_free_space(unsigned host)
647} 655}
648EXPORT_SYMBOL(qcom_smem_get_free_space); 656EXPORT_SYMBOL(qcom_smem_get_free_space);
649 657
658/**
659 * qcom_smem_virt_to_phys() - return the physical address associated
660 * with an smem item pointer (previously returned by qcom_smem_get()
661 * @p: the virtual address to convert
662 *
663 * Returns 0 if the pointer provided is not within any smem region.
664 */
665phys_addr_t qcom_smem_virt_to_phys(void *p)
666{
667 unsigned i;
668
669 for (i = 0; i < __smem->num_regions; i++) {
670 struct smem_region *region = &__smem->regions[i];
671
672 if (p < region->virt_base)
673 continue;
674 if (p < region->virt_base + region->size) {
675 u64 offset = p - region->virt_base;
676
677 return (phys_addr_t)region->aux_base + offset;
678 }
679 }
680
681 return 0;
682}
683EXPORT_SYMBOL(qcom_smem_virt_to_phys);
684
650static int qcom_smem_get_sbl_version(struct qcom_smem *smem) 685static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
651{ 686{
652 struct smem_header *header; 687 struct smem_header *header;
@@ -695,9 +730,10 @@ static u32 qcom_smem_get_item_count(struct qcom_smem *smem)
695static int qcom_smem_set_global_partition(struct qcom_smem *smem) 730static int qcom_smem_set_global_partition(struct qcom_smem *smem)
696{ 731{
697 struct smem_partition_header *header; 732 struct smem_partition_header *header;
698 struct smem_ptable_entry *entry = NULL; 733 struct smem_ptable_entry *entry;
699 struct smem_ptable *ptable; 734 struct smem_ptable *ptable;
700 u32 host0, host1, size; 735 u32 host0, host1, size;
736 bool found = false;
701 int i; 737 int i;
702 738
703 ptable = qcom_smem_get_ptable(smem); 739 ptable = qcom_smem_get_ptable(smem);
@@ -709,11 +745,13 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem)
709 host0 = le16_to_cpu(entry->host0); 745 host0 = le16_to_cpu(entry->host0);
710 host1 = le16_to_cpu(entry->host1); 746 host1 = le16_to_cpu(entry->host1);
711 747
712 if (host0 == SMEM_GLOBAL_HOST && host0 == host1) 748 if (host0 == SMEM_GLOBAL_HOST && host0 == host1) {
749 found = true;
713 break; 750 break;
751 }
714 } 752 }
715 753
716 if (!entry) { 754 if (!found) {
717 dev_err(smem->dev, "Missing entry for global partition\n"); 755 dev_err(smem->dev, "Missing entry for global partition\n");
718 return -EINVAL; 756 return -EINVAL;
719 } 757 }
@@ -723,11 +761,6 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem)
723 return -EINVAL; 761 return -EINVAL;
724 } 762 }
725 763
726 if (smem->global_partition) {
727 dev_err(smem->dev, "Already found the global partition\n");
728 return -EINVAL;
729 }
730
731 header = smem->regions[0].virt_base + le32_to_cpu(entry->offset); 764 header = smem->regions[0].virt_base + le32_to_cpu(entry->offset);
732 host0 = le16_to_cpu(header->host0); 765 host0 = le16_to_cpu(header->host0);
733 host1 = le16_to_cpu(header->host1); 766 host1 = le16_to_cpu(header->host1);