1 /*
2  * Copyright (c) 2014, The Linux Foundation. All rights reserved.
3  * Copyright (c) BayLibre, SAS.
4  * Author : Neil Armstrong <narmstrong@baylibre.com>
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15 
16 #include <linux/kernel.h>
17 #include <linux/bitops.h>
18 #include <linux/err.h>
19 #include <linux/platform_device.h>
20 #include <linux/module.h>
21 #include <linux/of.h>
22 #include <linux/of_device.h>
23 #include <linux/clk-provider.h>
24 #include <linux/regmap.h>
25 
26 #include <dt-bindings/clock/qcom,lcc-mdm9615.h>
27 
28 #include "common.h"
29 #include "clk-regmap.h"
30 #include "clk-pll.h"
31 #include "clk-rcg.h"
32 #include "clk-branch.h"
33 #include "clk-regmap-divider.h"
34 #include "clk-regmap-mux.h"
35 
36 static struct clk_pll pll4 = {
37 	.l_reg = 0x4,
38 	.m_reg = 0x8,
39 	.n_reg = 0xc,
40 	.config_reg = 0x14,
41 	.mode_reg = 0x0,
42 	.status_reg = 0x18,
43 	.status_bit = 16,
44 	.clkr.hw.init = &(struct clk_init_data){
45 		.name = "pll4",
46 		.parent_names = (const char *[]){ "cxo" },
47 		.num_parents = 1,
48 		.ops = &clk_pll_ops,
49 	},
50 };
51 
52 enum {
53 	P_CXO,
54 	P_PLL4,
55 };
56 
57 static const struct parent_map lcc_cxo_pll4_map[] = {
58 	{ P_CXO, 0 },
59 	{ P_PLL4, 2 }
60 };
61 
62 static const char * const lcc_cxo_pll4[] = {
63 	"cxo",
64 	"pll4_vote",
65 };
66 
67 static struct freq_tbl clk_tbl_aif_osr_492[] = {
68 	{   512000, P_PLL4, 4, 1, 240 },
69 	{   768000, P_PLL4, 4, 1, 160 },
70 	{  1024000, P_PLL4, 4, 1, 120 },
71 	{  1536000, P_PLL4, 4, 1,  80 },
72 	{  2048000, P_PLL4, 4, 1,  60 },
73 	{  3072000, P_PLL4, 4, 1,  40 },
74 	{  4096000, P_PLL4, 4, 1,  30 },
75 	{  6144000, P_PLL4, 4, 1,  20 },
76 	{  8192000, P_PLL4, 4, 1,  15 },
77 	{ 12288000, P_PLL4, 4, 1,  10 },
78 	{ 24576000, P_PLL4, 4, 1,   5 },
79 	{ 27000000, P_CXO,  1, 0,   0 },
80 	{ }
81 };
82 
83 static struct freq_tbl clk_tbl_aif_osr_393[] = {
84 	{   512000, P_PLL4, 4, 1, 192 },
85 	{   768000, P_PLL4, 4, 1, 128 },
86 	{  1024000, P_PLL4, 4, 1,  96 },
87 	{  1536000, P_PLL4, 4, 1,  64 },
88 	{  2048000, P_PLL4, 4, 1,  48 },
89 	{  3072000, P_PLL4, 4, 1,  32 },
90 	{  4096000, P_PLL4, 4, 1,  24 },
91 	{  6144000, P_PLL4, 4, 1,  16 },
92 	{  8192000, P_PLL4, 4, 1,  12 },
93 	{ 12288000, P_PLL4, 4, 1,   8 },
94 	{ 24576000, P_PLL4, 4, 1,   4 },
95 	{ 27000000, P_CXO,  1, 0,   0 },
96 	{ }
97 };
98 
99 static struct clk_rcg mi2s_osr_src = {
100 	.ns_reg = 0x48,
101 	.md_reg = 0x4c,
102 	.mn = {
103 		.mnctr_en_bit = 8,
104 		.mnctr_reset_bit = 7,
105 		.mnctr_mode_shift = 5,
106 		.n_val_shift = 24,
107 		.m_val_shift = 8,
108 		.width = 8,
109 	},
110 	.p = {
111 		.pre_div_shift = 3,
112 		.pre_div_width = 2,
113 	},
114 	.s = {
115 		.src_sel_shift = 0,
116 		.parent_map = lcc_cxo_pll4_map,
117 	},
118 	.freq_tbl = clk_tbl_aif_osr_393,
119 	.clkr = {
120 		.enable_reg = 0x48,
121 		.enable_mask = BIT(9),
122 		.hw.init = &(struct clk_init_data){
123 			.name = "mi2s_osr_src",
124 			.parent_names = lcc_cxo_pll4,
125 			.num_parents = 2,
126 			.ops = &clk_rcg_ops,
127 			.flags = CLK_SET_RATE_GATE,
128 		},
129 	},
130 };
131 
132 static const char * const lcc_mi2s_parents[] = {
133 	"mi2s_osr_src",
134 };
135 
136 static struct clk_branch mi2s_osr_clk = {
137 	.halt_reg = 0x50,
138 	.halt_bit = 1,
139 	.halt_check = BRANCH_HALT_ENABLE,
140 	.clkr = {
141 		.enable_reg = 0x48,
142 		.enable_mask = BIT(17),
143 		.hw.init = &(struct clk_init_data){
144 			.name = "mi2s_osr_clk",
145 			.parent_names = lcc_mi2s_parents,
146 			.num_parents = 1,
147 			.ops = &clk_branch_ops,
148 			.flags = CLK_SET_RATE_PARENT,
149 		},
150 	},
151 };
152 
153 static struct clk_regmap_div mi2s_div_clk = {
154 	.reg = 0x48,
155 	.shift = 10,
156 	.width = 4,
157 	.clkr = {
158 		.enable_reg = 0x48,
159 		.enable_mask = BIT(15),
160 		.hw.init = &(struct clk_init_data){
161 			.name = "mi2s_div_clk",
162 			.parent_names = lcc_mi2s_parents,
163 			.num_parents = 1,
164 			.ops = &clk_regmap_div_ops,
165 		},
166 	},
167 };
168 
169 static struct clk_branch mi2s_bit_div_clk = {
170 	.halt_reg = 0x50,
171 	.halt_bit = 0,
172 	.halt_check = BRANCH_HALT_ENABLE,
173 	.clkr = {
174 		.enable_reg = 0x48,
175 		.enable_mask = BIT(15),
176 		.hw.init = &(struct clk_init_data){
177 			.name = "mi2s_bit_div_clk",
178 			.parent_names = (const char *[]){ "mi2s_div_clk" },
179 			.num_parents = 1,
180 			.ops = &clk_branch_ops,
181 			.flags = CLK_SET_RATE_PARENT,
182 		},
183 	},
184 };
185 
186 static struct clk_regmap_mux mi2s_bit_clk = {
187 	.reg = 0x48,
188 	.shift = 14,
189 	.width = 1,
190 	.clkr = {
191 		.hw.init = &(struct clk_init_data){
192 			.name = "mi2s_bit_clk",
193 			.parent_names = (const char *[]){
194 				"mi2s_bit_div_clk",
195 				"mi2s_codec_clk",
196 			},
197 			.num_parents = 2,
198 			.ops = &clk_regmap_mux_closest_ops,
199 			.flags = CLK_SET_RATE_PARENT,
200 		},
201 	},
202 };
203 
204 #define CLK_AIF_OSR_DIV(prefix, _ns, _md, hr)			\
205 static struct clk_rcg prefix##_osr_src = {			\
206 	.ns_reg = _ns,						\
207 	.md_reg = _md,						\
208 	.mn = {							\
209 		.mnctr_en_bit = 8,				\
210 		.mnctr_reset_bit = 7,				\
211 		.mnctr_mode_shift = 5,				\
212 		.n_val_shift = 24,				\
213 		.m_val_shift = 8,				\
214 		.width = 8,					\
215 	},							\
216 	.p = {							\
217 		.pre_div_shift = 3,				\
218 		.pre_div_width = 2,				\
219 	},							\
220 	.s = {							\
221 		.src_sel_shift = 0,				\
222 		.parent_map = lcc_cxo_pll4_map,			\
223 	},							\
224 	.freq_tbl = clk_tbl_aif_osr_393,			\
225 	.clkr = {						\
226 		.enable_reg = _ns,				\
227 		.enable_mask = BIT(9),				\
228 		.hw.init = &(struct clk_init_data){		\
229 			.name = #prefix "_osr_src",		\
230 			.parent_names = lcc_cxo_pll4,		\
231 			.num_parents = 2,			\
232 			.ops = &clk_rcg_ops,			\
233 			.flags = CLK_SET_RATE_GATE,		\
234 		},						\
235 	},							\
236 };								\
237 								\
238 static const char * const lcc_##prefix##_parents[] = {		\
239 	#prefix "_osr_src",					\
240 };								\
241 								\
242 static struct clk_branch prefix##_osr_clk = {			\
243 	.halt_reg = hr,						\
244 	.halt_bit = 1,						\
245 	.halt_check = BRANCH_HALT_ENABLE,			\
246 	.clkr = {						\
247 		.enable_reg = _ns,				\
248 		.enable_mask = BIT(21),				\
249 		.hw.init = &(struct clk_init_data){		\
250 			.name = #prefix "_osr_clk",		\
251 			.parent_names = lcc_##prefix##_parents,	\
252 			.num_parents = 1,			\
253 			.ops = &clk_branch_ops,			\
254 			.flags = CLK_SET_RATE_PARENT,		\
255 		},						\
256 	},							\
257 };								\
258 								\
259 static struct clk_regmap_div prefix##_div_clk = {		\
260 	.reg = _ns,						\
261 	.shift = 10,						\
262 	.width = 8,						\
263 	.clkr = {						\
264 		.hw.init = &(struct clk_init_data){		\
265 			.name = #prefix "_div_clk",		\
266 			.parent_names = lcc_##prefix##_parents,	\
267 			.num_parents = 1,			\
268 			.ops = &clk_regmap_div_ops,		\
269 		},						\
270 	},							\
271 };								\
272 								\
273 static struct clk_branch prefix##_bit_div_clk = {		\
274 	.halt_reg = hr,						\
275 	.halt_bit = 0,						\
276 	.halt_check = BRANCH_HALT_ENABLE,			\
277 	.clkr = {						\
278 		.enable_reg = _ns,				\
279 		.enable_mask = BIT(19),				\
280 		.hw.init = &(struct clk_init_data){		\
281 			.name = #prefix "_bit_div_clk",		\
282 			.parent_names = (const char *[]){	\
283 				#prefix "_div_clk"		\
284 			},					\
285 			.num_parents = 1,			\
286 			.ops = &clk_branch_ops,			\
287 			.flags = CLK_SET_RATE_PARENT,		\
288 		},						\
289 	},							\
290 };								\
291 								\
292 static struct clk_regmap_mux prefix##_bit_clk = {		\
293 	.reg = _ns,						\
294 	.shift = 18,						\
295 	.width = 1,						\
296 	.clkr = {						\
297 		.hw.init = &(struct clk_init_data){		\
298 			.name = #prefix "_bit_clk",		\
299 			.parent_names = (const char *[]){	\
300 				#prefix "_bit_div_clk",		\
301 				#prefix "_codec_clk",		\
302 			},					\
303 			.num_parents = 2,			\
304 			.ops = &clk_regmap_mux_closest_ops,	\
305 			.flags = CLK_SET_RATE_PARENT,		\
306 		},						\
307 	},							\
308 }
309 
310 CLK_AIF_OSR_DIV(codec_i2s_mic, 0x60, 0x64, 0x68);
311 CLK_AIF_OSR_DIV(spare_i2s_mic, 0x78, 0x7c, 0x80);
312 CLK_AIF_OSR_DIV(codec_i2s_spkr, 0x6c, 0x70, 0x74);
313 CLK_AIF_OSR_DIV(spare_i2s_spkr, 0x84, 0x88, 0x8c);
314 
315 static struct freq_tbl clk_tbl_pcm_492[] = {
316 	{   256000, P_PLL4, 4, 1, 480 },
317 	{   512000, P_PLL4, 4, 1, 240 },
318 	{   768000, P_PLL4, 4, 1, 160 },
319 	{  1024000, P_PLL4, 4, 1, 120 },
320 	{  1536000, P_PLL4, 4, 1,  80 },
321 	{  2048000, P_PLL4, 4, 1,  60 },
322 	{  3072000, P_PLL4, 4, 1,  40 },
323 	{  4096000, P_PLL4, 4, 1,  30 },
324 	{  6144000, P_PLL4, 4, 1,  20 },
325 	{  8192000, P_PLL4, 4, 1,  15 },
326 	{ 12288000, P_PLL4, 4, 1,  10 },
327 	{ 24576000, P_PLL4, 4, 1,   5 },
328 	{ 27000000, P_CXO,  1, 0,   0 },
329 	{ }
330 };
331 
332 static struct freq_tbl clk_tbl_pcm_393[] = {
333 	{   256000, P_PLL4, 4, 1, 384 },
334 	{   512000, P_PLL4, 4, 1, 192 },
335 	{   768000, P_PLL4, 4, 1, 128 },
336 	{  1024000, P_PLL4, 4, 1,  96 },
337 	{  1536000, P_PLL4, 4, 1,  64 },
338 	{  2048000, P_PLL4, 4, 1,  48 },
339 	{  3072000, P_PLL4, 4, 1,  32 },
340 	{  4096000, P_PLL4, 4, 1,  24 },
341 	{  6144000, P_PLL4, 4, 1,  16 },
342 	{  8192000, P_PLL4, 4, 1,  12 },
343 	{ 12288000, P_PLL4, 4, 1,   8 },
344 	{ 24576000, P_PLL4, 4, 1,   4 },
345 	{ 27000000, P_CXO,  1, 0,   0 },
346 	{ }
347 };
348 
349 static struct clk_rcg pcm_src = {
350 	.ns_reg = 0x54,
351 	.md_reg = 0x58,
352 	.mn = {
353 		.mnctr_en_bit = 8,
354 		.mnctr_reset_bit = 7,
355 		.mnctr_mode_shift = 5,
356 		.n_val_shift = 16,
357 		.m_val_shift = 16,
358 		.width = 16,
359 	},
360 	.p = {
361 		.pre_div_shift = 3,
362 		.pre_div_width = 2,
363 	},
364 	.s = {
365 		.src_sel_shift = 0,
366 		.parent_map = lcc_cxo_pll4_map,
367 	},
368 	.freq_tbl = clk_tbl_pcm_393,
369 	.clkr = {
370 		.enable_reg = 0x54,
371 		.enable_mask = BIT(9),
372 		.hw.init = &(struct clk_init_data){
373 			.name = "pcm_src",
374 			.parent_names = lcc_cxo_pll4,
375 			.num_parents = 2,
376 			.ops = &clk_rcg_ops,
377 			.flags = CLK_SET_RATE_GATE,
378 		},
379 	},
380 };
381 
382 static struct clk_branch pcm_clk_out = {
383 	.halt_reg = 0x5c,
384 	.halt_bit = 0,
385 	.halt_check = BRANCH_HALT_ENABLE,
386 	.clkr = {
387 		.enable_reg = 0x54,
388 		.enable_mask = BIT(11),
389 		.hw.init = &(struct clk_init_data){
390 			.name = "pcm_clk_out",
391 			.parent_names = (const char *[]){ "pcm_src" },
392 			.num_parents = 1,
393 			.ops = &clk_branch_ops,
394 			.flags = CLK_SET_RATE_PARENT,
395 		},
396 	},
397 };
398 
399 static struct clk_regmap_mux pcm_clk = {
400 	.reg = 0x54,
401 	.shift = 10,
402 	.width = 1,
403 	.clkr = {
404 		.hw.init = &(struct clk_init_data){
405 			.name = "pcm_clk",
406 			.parent_names = (const char *[]){
407 				"pcm_clk_out",
408 				"pcm_codec_clk",
409 			},
410 			.num_parents = 2,
411 			.ops = &clk_regmap_mux_closest_ops,
412 			.flags = CLK_SET_RATE_PARENT,
413 		},
414 	},
415 };
416 
417 static struct clk_rcg slimbus_src = {
418 	.ns_reg = 0xcc,
419 	.md_reg = 0xd0,
420 	.mn = {
421 		.mnctr_en_bit = 8,
422 		.mnctr_reset_bit = 7,
423 		.mnctr_mode_shift = 5,
424 		.n_val_shift = 24,
425 		.m_val_shift = 8,
426 		.width = 8,
427 	},
428 	.p = {
429 		.pre_div_shift = 3,
430 		.pre_div_width = 2,
431 	},
432 	.s = {
433 		.src_sel_shift = 0,
434 		.parent_map = lcc_cxo_pll4_map,
435 	},
436 	.freq_tbl = clk_tbl_aif_osr_393,
437 	.clkr = {
438 		.enable_reg = 0xcc,
439 		.enable_mask = BIT(9),
440 		.hw.init = &(struct clk_init_data){
441 			.name = "slimbus_src",
442 			.parent_names = lcc_cxo_pll4,
443 			.num_parents = 2,
444 			.ops = &clk_rcg_ops,
445 			.flags = CLK_SET_RATE_GATE,
446 		},
447 	},
448 };
449 
450 static const char * const lcc_slimbus_parents[] = {
451 	"slimbus_src",
452 };
453 
454 static struct clk_branch audio_slimbus_clk = {
455 	.halt_reg = 0xd4,
456 	.halt_bit = 0,
457 	.halt_check = BRANCH_HALT_ENABLE,
458 	.clkr = {
459 		.enable_reg = 0xcc,
460 		.enable_mask = BIT(10),
461 		.hw.init = &(struct clk_init_data){
462 			.name = "audio_slimbus_clk",
463 			.parent_names = lcc_slimbus_parents,
464 			.num_parents = 1,
465 			.ops = &clk_branch_ops,
466 			.flags = CLK_SET_RATE_PARENT,
467 		},
468 	},
469 };
470 
471 static struct clk_branch sps_slimbus_clk = {
472 	.halt_reg = 0xd4,
473 	.halt_bit = 1,
474 	.halt_check = BRANCH_HALT_ENABLE,
475 	.clkr = {
476 		.enable_reg = 0xcc,
477 		.enable_mask = BIT(12),
478 		.hw.init = &(struct clk_init_data){
479 			.name = "sps_slimbus_clk",
480 			.parent_names = lcc_slimbus_parents,
481 			.num_parents = 1,
482 			.ops = &clk_branch_ops,
483 			.flags = CLK_SET_RATE_PARENT,
484 		},
485 	},
486 };
487 
488 static struct clk_regmap *lcc_mdm9615_clks[] = {
489 	[PLL4] = &pll4.clkr,
490 	[MI2S_OSR_SRC] = &mi2s_osr_src.clkr,
491 	[MI2S_OSR_CLK] = &mi2s_osr_clk.clkr,
492 	[MI2S_DIV_CLK] = &mi2s_div_clk.clkr,
493 	[MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr,
494 	[MI2S_BIT_CLK] = &mi2s_bit_clk.clkr,
495 	[PCM_SRC] = &pcm_src.clkr,
496 	[PCM_CLK_OUT] = &pcm_clk_out.clkr,
497 	[PCM_CLK] = &pcm_clk.clkr,
498 	[SLIMBUS_SRC] = &slimbus_src.clkr,
499 	[AUDIO_SLIMBUS_CLK] = &audio_slimbus_clk.clkr,
500 	[SPS_SLIMBUS_CLK] = &sps_slimbus_clk.clkr,
501 	[CODEC_I2S_MIC_OSR_SRC] = &codec_i2s_mic_osr_src.clkr,
502 	[CODEC_I2S_MIC_OSR_CLK] = &codec_i2s_mic_osr_clk.clkr,
503 	[CODEC_I2S_MIC_DIV_CLK] = &codec_i2s_mic_div_clk.clkr,
504 	[CODEC_I2S_MIC_BIT_DIV_CLK] = &codec_i2s_mic_bit_div_clk.clkr,
505 	[CODEC_I2S_MIC_BIT_CLK] = &codec_i2s_mic_bit_clk.clkr,
506 	[SPARE_I2S_MIC_OSR_SRC] = &spare_i2s_mic_osr_src.clkr,
507 	[SPARE_I2S_MIC_OSR_CLK] = &spare_i2s_mic_osr_clk.clkr,
508 	[SPARE_I2S_MIC_DIV_CLK] = &spare_i2s_mic_div_clk.clkr,
509 	[SPARE_I2S_MIC_BIT_DIV_CLK] = &spare_i2s_mic_bit_div_clk.clkr,
510 	[SPARE_I2S_MIC_BIT_CLK] = &spare_i2s_mic_bit_clk.clkr,
511 	[CODEC_I2S_SPKR_OSR_SRC] = &codec_i2s_spkr_osr_src.clkr,
512 	[CODEC_I2S_SPKR_OSR_CLK] = &codec_i2s_spkr_osr_clk.clkr,
513 	[CODEC_I2S_SPKR_DIV_CLK] = &codec_i2s_spkr_div_clk.clkr,
514 	[CODEC_I2S_SPKR_BIT_DIV_CLK] = &codec_i2s_spkr_bit_div_clk.clkr,
515 	[CODEC_I2S_SPKR_BIT_CLK] = &codec_i2s_spkr_bit_clk.clkr,
516 	[SPARE_I2S_SPKR_OSR_SRC] = &spare_i2s_spkr_osr_src.clkr,
517 	[SPARE_I2S_SPKR_OSR_CLK] = &spare_i2s_spkr_osr_clk.clkr,
518 	[SPARE_I2S_SPKR_DIV_CLK] = &spare_i2s_spkr_div_clk.clkr,
519 	[SPARE_I2S_SPKR_BIT_DIV_CLK] = &spare_i2s_spkr_bit_div_clk.clkr,
520 	[SPARE_I2S_SPKR_BIT_CLK] = &spare_i2s_spkr_bit_clk.clkr,
521 };
522 
523 static const struct regmap_config lcc_mdm9615_regmap_config = {
524 	.reg_bits	= 32,
525 	.reg_stride	= 4,
526 	.val_bits	= 32,
527 	.max_register	= 0xfc,
528 	.fast_io	= true,
529 };
530 
531 static const struct qcom_cc_desc lcc_mdm9615_desc = {
532 	.config = &lcc_mdm9615_regmap_config,
533 	.clks = lcc_mdm9615_clks,
534 	.num_clks = ARRAY_SIZE(lcc_mdm9615_clks),
535 };
536 
537 static const struct of_device_id lcc_mdm9615_match_table[] = {
538 	{ .compatible = "qcom,lcc-mdm9615" },
539 	{ }
540 };
541 MODULE_DEVICE_TABLE(of, lcc_mdm9615_match_table);
542 
lcc_mdm9615_probe(struct platform_device * pdev)543 static int lcc_mdm9615_probe(struct platform_device *pdev)
544 {
545 	u32 val;
546 	struct regmap *regmap;
547 
548 	regmap = qcom_cc_map(pdev, &lcc_mdm9615_desc);
549 	if (IS_ERR(regmap))
550 		return PTR_ERR(regmap);
551 
552 	/* Use the correct frequency plan depending on speed of PLL4 */
553 	regmap_read(regmap, 0x4, &val);
554 	if (val == 0x12) {
555 		slimbus_src.freq_tbl = clk_tbl_aif_osr_492;
556 		mi2s_osr_src.freq_tbl = clk_tbl_aif_osr_492;
557 		codec_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492;
558 		spare_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492;
559 		codec_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492;
560 		spare_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492;
561 		pcm_src.freq_tbl = clk_tbl_pcm_492;
562 	}
563 	/* Enable PLL4 source on the LPASS Primary PLL Mux */
564 	regmap_write(regmap, 0xc4, 0x1);
565 
566 	return qcom_cc_really_probe(pdev, &lcc_mdm9615_desc, regmap);
567 }
568 
569 static struct platform_driver lcc_mdm9615_driver = {
570 	.probe		= lcc_mdm9615_probe,
571 	.driver		= {
572 		.name	= "lcc-mdm9615",
573 		.of_match_table = lcc_mdm9615_match_table,
574 	},
575 };
576 module_platform_driver(lcc_mdm9615_driver);
577 
578 MODULE_DESCRIPTION("QCOM LCC MDM9615 Driver");
579 MODULE_LICENSE("GPL v2");
580 MODULE_ALIAS("platform:lcc-mdm9615");
581