1/* Copyright (c) 2013,2015, The Linux Foundation. All rights reserved.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 *
16 *
17 */
18#include <linux/types.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/slab.h>
22#include <linux/device.h>
23#include <linux/memory.h>
24#include <linux/io.h>
25#include <linux/clk.h>
26#include <linux/uaccess.h>
27#include <linux/dma-mapping.h>
28#include <linux/platform_device.h>
29#include <mach/msm_iomap.h>
30#include <mach/msm_nss_crypto.h>
31#include <linux/interrupt.h>
32#include <linux/delay.h>
33#include <linux/vmalloc.h>
34#include <nss_crypto_hlos.h>
35#include <nss_api_if.h>
36#include <nss_crypto.h>
37#include <nss_crypto_if.h>
38#include <nss_crypto_hw.h>
39#include <nss_crypto_ctrl.h>
40#include <nss_crypto_dbg.h>
41#include <nss_crypto_debugfs.h>
42
43#define REG(off)	(MSM_CLK_CTL_BASE + (off))
44#define REG_GCC(off)	(MSM_APCS_GCC_BASE + (off))
45
46#define CRYPTO_RESET_ENG(n)	REG(0x3E00 + (n * 0x4))
47#define CRYPTO_RESET_AHB	REG(0x3E10)
48
49#define CRYPTO_RESET_ENG_0	REG(0x3E00)
50#define CRYPTO_RESET_ENG_1	REG(0x3E04)
51#define CRYPTO_RESET_ENG_2	REG(0x3E08)
52#define CRYPTO_RESET_ENG_3	REG(0x3E0C)
53
54/* Poll time in ms */
55#define CRYPTO_DELAYED_INIT_TIME	100
56
57extern struct nss_crypto_ctrl gbl_crypto_ctrl;
58extern struct nss_ctx_instance *nss_drv_hdl;
59
60static int eng_count;
61
62void nss_crypto_engine_init(uint32_t eng_count);
63void nss_crypto_init(void);
64
65/*
66 * nss_crypto_bam_init()
67 * 	initialize the BAM for the given engine
68 */
69static void nss_crypto_bam_init(uint8_t *bam_iobase)
70{
71	uint32_t cfg_bits;
72	uint32_t ctrl_reg;
73
74	ctrl_reg = ioread32(bam_iobase + CRYPTO_BAM_CTRL);
75
76	ctrl_reg |= CRYPTO_BAM_CTRL_SW_RST;
77	iowrite32(ctrl_reg, bam_iobase + CRYPTO_BAM_CTRL);
78
79	ctrl_reg &= ~CRYPTO_BAM_CTRL_SW_RST;
80	iowrite32(ctrl_reg, bam_iobase + CRYPTO_BAM_CTRL);
81
82	ctrl_reg |= CRYPTO_BAM_CTRL_BAM_EN;
83	iowrite32(ctrl_reg, bam_iobase + CRYPTO_BAM_CTRL);
84
85	iowrite32(CRYPTO_BAM_DESC_CNT_TRSHLD_VAL, bam_iobase +  CRYPTO_BAM_DESC_CNT_TRSHLD);
86
87	/* disabling this is recommended from H/W specification*/
88	cfg_bits = ~((uint32_t)CRYPTO_BAM_CNFG_BITS_BAM_FULL_PIPE);
89	iowrite32(cfg_bits, bam_iobase + CRYPTO_BAM_CNFG_BITS);
90}
91
92/*
93 * nss_crypto_probe()
94 * 	probe routine called per engine from MACH-MSM
95 */
96static int nss_crypto_probe(struct platform_device *pdev)
97{
98	struct nss_crypto_ctrl_eng *e_ctrl;
99	struct nss_crypto_platform_data *res;
100	struct nss_crypto_ctrl_eng *eng_ptr;
101	int status = 0;
102	size_t old_sz;
103	size_t new_sz;
104
105	nss_crypto_info_always("probing engine - %d\n", eng_count);
106	nss_crypto_assert(eng_count < NSS_CRYPTO_MAX_ENGINES);
107
108	eng_ptr = gbl_crypto_ctrl.eng;
109
110	old_sz = (gbl_crypto_ctrl.num_eng * sizeof(struct nss_crypto_ctrl_eng));
111	new_sz = old_sz + sizeof(struct nss_crypto_ctrl_eng);
112
113	eng_ptr = nss_crypto_mem_realloc(eng_ptr, old_sz, new_sz);
114	if (eng_ptr == NULL) {
115		return -ENOMEM;
116	}
117
118	gbl_crypto_ctrl.eng = eng_ptr;
119
120	e_ctrl = &gbl_crypto_ctrl.eng[eng_count];
121	e_ctrl->dev = &pdev->dev;
122
123	/* crypto engine resources */
124	res = dev_get_platdata(e_ctrl->dev);
125	nss_crypto_assert(res);
126
127	e_ctrl->bam_ee = res->bam_ee;
128
129	e_ctrl->cmd_base = res->crypto_pbase;
130	e_ctrl->crypto_base = ioremap_nocache(res->crypto_pbase, res->crypto_pbase_sz);
131	nss_crypto_assert(e_ctrl->crypto_base);
132
133	e_ctrl->bam_pbase = res->bam_pbase;
134	e_ctrl->bam_base = ioremap_nocache(res->bam_pbase, res->bam_pbase_sz);
135	nss_crypto_assert(e_ctrl->bam_base);
136
137	/*
138	 * Link address of engine ctrl
139	 */
140	platform_set_drvdata(pdev, e_ctrl);
141
142	/*
143	 * intialize the BAM and the engine
144	 */
145	nss_crypto_bam_init(e_ctrl->bam_base);
146	nss_crypto_engine_init(eng_count);
147
148	eng_count++;
149	gbl_crypto_ctrl.num_eng = eng_count;
150
151	return status;
152}
153
154/*
155 * nss_crypto_remove()
156 * 	remove the crypto engine and deregister everything
157 */
158static int nss_crypto_remove(struct platform_device *pdev)
159{
160	struct nss_crypto_ctrl_eng *ctrl;
161
162	ctrl = platform_get_drvdata(pdev);
163
164	/**
165	 * XXX: pipe deinit goes here
166	 */
167	return 0;
168};
169
170/*
171 * platform device instance
172 */
173static struct platform_driver nss_crypto_drv = {
174	.probe  	= nss_crypto_probe,
175	.remove 	= nss_crypto_remove,
176	.driver 	= {
177		.owner  = THIS_MODULE,
178		.name   = "nss-crypto",
179	},
180};
181
182/*
183 * nss_crypto_module_exit()
184 * 	module exit for crypto driver
185 */
186static void __exit nss_crypto_module_exit(void)
187{
188	nss_crypto_info("module unloaded (IPQ806x)\n");
189
190	platform_driver_unregister(&nss_crypto_drv);
191}
192
193void nss_crypto_delayed_init(struct work_struct *work)
194{
195	struct nss_crypto_ctrl *ctrl;
196	uint32_t status = 0;
197	uint32_t i = 0;
198
199	ctrl = container_of(to_delayed_work(work), struct nss_crypto_ctrl, crypto_work);
200
201	/*
202	 * check if NSS FW is initialized
203	 */
204	if (nss_get_state(nss_drv_hdl) != NSS_STATE_INITIALIZED) {
205		schedule_delayed_work(&ctrl->crypto_work, msecs_to_jiffies(CRYPTO_DELAYED_INIT_TIME));
206		return;
207	}
208
209	nss_crypto_info_always("NSS Firmware initialized\n");
210
211	/*
212	 * reserve the index if certain pipe pairs are locked out for
213	 * trust zone use
214	 */
215	ctrl->idx_bitmap = 0;
216
217	status = platform_driver_register(&nss_crypto_drv);
218	if (status != 0) {
219		nss_crypto_err("unable to register the driver : %d\n", status);
220		return;
221	}
222
223	/*
224	 * Initialize the engine stats
225	 */
226	for (i = 0; i < gbl_crypto_ctrl.num_eng ; i++)
227		nss_crypto_debugfs_add_engine(ctrl, i);
228}
229
230/*
231 * nss_crypto_module_init()
232 * 	module init for crypto driver
233 */
234static int __init nss_crypto_module_init(void)
235{
236
237	nss_crypto_info("module loaded (platform - IPQ806x, build - %s:%s)\n", __DATE__, __TIME__);
238
239	/*
240	 * bring the crypto out of reset
241	 */
242	iowrite32(0, CRYPTO_RESET_ENG(0));
243	iowrite32(0, CRYPTO_RESET_ENG(1));
244	iowrite32(0, CRYPTO_RESET_ENG(2));
245	iowrite32(0, CRYPTO_RESET_ENG(3));
246
247	iowrite32(0, CRYPTO_RESET_AHB);
248
249	nss_crypto_init();
250
251	nss_crypto_info_always("Register with NSS driver-\n");
252
253	INIT_DELAYED_WORK(&gbl_crypto_ctrl.crypto_work, nss_crypto_delayed_init);
254
255	schedule_delayed_work(&gbl_crypto_ctrl.crypto_work, msecs_to_jiffies(CRYPTO_DELAYED_INIT_TIME));
256
257	return 0;
258}
259
260module_init(nss_crypto_module_init);
261module_exit(nss_crypto_module_exit);
262
263MODULE_LICENSE("Dual BSD/GPL");
264MODULE_DESCRIPTION("QCA NSS Crypto driver");
265MODULE_AUTHOR("Qualcomm Atheros Inc");
266