blob: 5f82f421e2e79d7fdda7734817430cc71dac7454 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * Marvell SLIC driver
3 *
4 * Copyright (C) 2014 Marvell Technology Group Ltd.
5 *
6 * Author: Yu Zhang <zhangy@marvell.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 */
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/init.h>
21#include <linux/gpio.h>
22#include <linux/of.h>
23#include <linux/of_gpio.h>
24#include <linux/delay.h>
25#include <linux/regulator/machine.h>
26#include <linux/platform_device.h>
27#include <linux/pinctrl/consumer.h>
28#include <linux/edge_wakeup_mmp.h>
29#include <linux/mfd/88pm80x.h>
30#include <soc/asr/addr-map.h>
31
32#define SLIC_STATUS_LENS 8
33
34struct nz3_slic_info {
35 struct device *dev;
36 char chip_status[SLIC_STATUS_LENS];
37 char reset_status[SLIC_STATUS_LENS];
38 int reset_n_gpio;
39 int edge_wakeup_gpio;
40 int vdd_3v3_gpio;
41 struct pinctrl *pinctrl;
42 struct pinctrl_state *pin_lpm_drv_low;
43 struct pinctrl_state *pin_lpm_drv_high;
44 struct regulator *vdd_3v3;
45};
46
47static struct pinctrl *g_nz3_slic_pinctrl = NULL;
48
49static int g_reset_n_gpio = -1;
50static int g_edge_wakeup_gpio = -1;
51static int g_vdd_3v3_gpio = -1;
52
53//#define DEBUG_FALCON_SLIC_RESET
54#ifdef DEBUG_FALCON_SLIC_RESET
55
56#define MFPR_VIRT_BASE (APB_VIRT_BASE + 0x1e000)
57
58static void __iomem *APBC_AIB_CLK_RST_reg = APB_VIRT_BASE + 0x15000 + 0x3C;/* 0xD4015000+0x3C */
59static void __iomem *GPIO10_MFPR_reg = MFPR_VIRT_BASE + 0x104;/* 0xD401E000+0x104 */
60static void __iomem *APBC_GPIO_CLK_RST_reg = APB_VIRT_BASE + 0x15000 + 0x8;/* 0xD4015008 */
61static void __iomem *GPIO_PDR0_reg = APB_VIRT_BASE + 0x19000 +0xC;/* 0xD4019000+0xC */
62#if 0
63static void __iomem *GPIO_PSR0_reg = APB_VIRT_BASE + 0x19000 +0x18;/* 0xD4019000+0x18 */
64static void __iomem *GPIO_PCR0_reg = APB_VIRT_BASE + 0x19000 +0x24;/* 0xD4019000+0x24 */
65#endif
66
67static void falcon_config_MFPR_GPIO10(void)
68{
69 int reg_value = 0;
70
71 printk(KERN_INFO"%s:L%d, enter.\n", __FUNCTION__, __LINE__);
72
73 if (!APBC_AIB_CLK_RST_reg ||!GPIO10_MFPR_reg ||!APBC_GPIO_CLK_RST_reg || !GPIO_PDR0_reg)
74 {
75 printk(KERN_INFO"%s:L%d, NULL pointer.\n", __FUNCTION__, __LINE__);
76 return;
77 }
78
79 //*(volatile unsigned int *)APBC_AIB_CLK_RST_reg = 0xFFFFFFFB;/* open aib MFPR config clock/rst */
80 __raw_writel(0xFFFFFFFB, APBC_AIB_CLK_RST_reg);
81
82 //*(volatile unsigned int *)GPIO10_MFPR_reg &= ~((0x3<<13) | 0x7);/* use function 0 to select gpio_in[10], and NO Pull up/dn */
83 reg_value = __raw_readl(GPIO10_MFPR_reg);
84 printk(KERN_INFO"%s,GPIO10_MFPR_reg value before= 0x%x\n", __FUNCTION__, reg_value);
85 reg_value &= ~((0x3<<13) | 0x7);
86 __raw_writel(reg_value, GPIO10_MFPR_reg);/* Falcon */
87 printk(KERN_INFO"%s,GPIO10_MFPR_reg value after= 0x%x\n", __FUNCTION__, reg_value);
88
89 //*(volatile unsigned int *)APBC_GPIO_CLK_RST_reg = 0x3;/* gpio clock/rst enable */
90 __raw_writel(0x3, APBC_GPIO_CLK_RST_reg);
91
92 //*(volatile unsigned int *)GPIO_PDR0_reg |= 0x1<<10;/* gpio_in[10] output */
93 reg_value = __raw_readl(GPIO_PDR0_reg);
94 reg_value |= 0x1<<10;
95 __raw_writel(reg_value, GPIO_PDR0_reg);/* Falcon */
96
97 return;
98}
99#endif
100
101static void slic_power_on(struct nz3_slic_info *info)
102{
103 if (!strncmp(info->chip_status, "on", 2)) {
104 dev_info(info->dev, "slic chip already powered on\n");
105 return;
106 }
107
108 if (info->vdd_3v3 > 0) {
109 if (regulator_set_voltage(info->vdd_3v3, 3300000, 3300000))
110 pr_err("fail to set regulator wib_3v3 supply 2 to 3.3v\n");
111 if (regulator_enable(info->vdd_3v3))
112 pr_err("fail to enable regulator vdd_3v3\n");
113 }
114
115 if (info->vdd_3v3_gpio >= 0) {
116 gpio_direction_output(info->vdd_3v3_gpio, 1);
117 }
118
119 usleep_range(65, 70);
120#ifdef DEBUG_FALCON_SLIC_RESET
121 if (cpu_is_asr1803()) {
122 falcon_config_MFPR_GPIO10();
123 }
124#endif
125 if (info->reset_n_gpio >= 0) {
126 gpio_direction_output(info->reset_n_gpio, 1);
127 strncpy(info->reset_status, "high", 5);
128 }
129
130 strncpy(info->chip_status, "on", 3);
131
132 if (info->vdd_3v3 > 0) {
133 buck2_ldo8_sleepmode_control_for_slic(1);
134 }
135
136 dev_info(info->dev, "slic chip powered on\n");
137}
138
139static void slic_power_off(struct nz3_slic_info *info)
140{
141 if (!strncmp(info->chip_status, "off", 3)) {
142 dev_info(info->dev, "slic chip already powered off\n");
143 return;
144 }
145
146 if (info->vdd_3v3 > 0) {
147 if (regulator_disable(info->vdd_3v3))
148 pr_err("fail to disable regulator vdd_3v3\n");
149 }
150
151 if (info->vdd_3v3_gpio >= 0) {
152 gpio_direction_output(info->vdd_3v3_gpio, 0);
153 }
154#ifdef DEBUG_FALCON_SLIC_RESET
155 if (cpu_is_asr1803()) {
156 falcon_config_MFPR_GPIO10();
157 }
158#endif
159 if (info->reset_n_gpio >= 0) {
160 gpio_direction_output(info->reset_n_gpio, 0);
161 strncpy(info->reset_status, "low", 4);
162 }
163
164 strncpy(info->chip_status, "off", 4);
165
166 if (info->vdd_3v3 > 0) {
167 buck2_ldo8_sleepmode_control_for_slic(0);
168 }
169
170 dev_info(info->dev, "slic chip powered off\n");
171}
172
173static void slic_reset(struct nz3_slic_info *info, int flag)
174{
175 printk(KERN_INFO "%s, reset_n_gpio=%d, flag=%d.\n", __FUNCTION__, info->reset_n_gpio, flag);
176#ifdef DEBUG_FALCON_SLIC_RESET
177 if (cpu_is_asr1803()) {
178 falcon_config_MFPR_GPIO10();
179 }
180#endif
181 gpio_direction_output(info->reset_n_gpio, flag);
182
183 sprintf(info->reset_status, "%s", flag ? "high" : "low");
184 dev_info(info->dev, "slic chip reset_n set to %s\n",
185 flag ? "high" : "low");
186}
187
188static ssize_t slic_ctrl(struct device *dev,
189 struct device_attribute *attr,
190 const char *buf, size_t count)
191{
192 static char msg[64];
193 int flag, ret;
194
195 struct nz3_slic_info *info = dev_get_drvdata(dev);
196
197 count = (count > 64) ? 64 : count;
198 memset(msg, 0, count);
199
200 if (!strncmp(buf, "off", 3)) {
201 slic_power_off(info);
202 } else if (!strncmp(buf, "on", 2)) {
203 slic_power_on(info);
204 } else if (!strncmp(buf, "reset", 5)) {
205 ret = sscanf(buf, "%s %d", msg, &flag);
206 if (ret == 2)
207 slic_reset(info, flag);
208 } else
209 dev_info(info->dev, "usage wrong\n");
210
211 return count;
212}
213
214static ssize_t slic_status(struct device *dev,
215 struct device_attribute *attr, char *buf)
216{
217 struct nz3_slic_info *info = dev_get_drvdata(dev);
218
219 return sprintf(buf, "power: %s, reset_n: %s\n", info->chip_status,
220 info->reset_status);
221}
222
223static DEVICE_ATTR(ctrl, S_IWUSR, slic_status, slic_ctrl);
224static DEVICE_ATTR(status, S_IRUSR, slic_status, NULL);
225
226static const struct attribute *slic_attrs[] = {
227 &dev_attr_ctrl.attr,
228 &dev_attr_status.attr,
229 NULL,
230};
231
232static const struct attribute_group slic_attr_group = {
233 .attrs = (struct attribute **)slic_attrs,
234};
235
236#ifdef CONFIG_OF
237static int nz3_slic_dt_init(struct device_node *np,
238 struct device *dev,
239 struct nz3_slic_info *info)
240{
241
242 struct regulator *vdd_3v3 = NULL;
243
244 info->reset_n_gpio =
245 of_get_named_gpio(dev->of_node, "rst-gpio", 0);
246 if (info->reset_n_gpio < 0) {
247 dev_err(dev, "%s: of_get_named_gpio failed: %d\n", __func__,
248 info->reset_n_gpio);
249 info->reset_n_gpio = -1;
250 goto out;
251 }
252
253 info->edge_wakeup_gpio =
254 of_get_named_gpio(dev->of_node, "edge-wakeup-gpio", 0);
255 if (info->edge_wakeup_gpio < 0) {
256 dev_err(dev, "%s: of_get_named_gpio failed: %d\n", __func__,
257 info->edge_wakeup_gpio);
258 info->edge_wakeup_gpio = -1;
259 goto out;
260 }
261
262 info->vdd_3v3_gpio = of_get_named_gpio(dev->of_node, "vdd-3v3-gpio", 0);
263 if (info->vdd_3v3_gpio < 0) {
264 dev_err(dev, "%s: of_get_named_gpio failed: %d\n", __func__, info->vdd_3v3_gpio);
265 info->vdd_3v3_gpio = -1;
266 }
267
268 g_reset_n_gpio = info->reset_n_gpio;
269 g_edge_wakeup_gpio = info->edge_wakeup_gpio;
270 g_vdd_3v3_gpio = info->vdd_3v3_gpio;
271
272 printk(KERN_INFO"%s: reset_n_gpio=%d, edge_wakeup_gpio=%d, vdd_3v3_gpio=%d, %s.\n",
273 __FUNCTION__, info->reset_n_gpio, info->edge_wakeup_gpio, info->vdd_3v3_gpio, (info->vdd_3v3_gpio < 0)?"ASR1826 Old DKB":"ASR1826 New DKB");
274
275 printk(KERN_INFO"%s: g_reset_n_gpio=%d, g_edge_wakeup_gpio=%d, g_vdd_3v3_gpio=%d.\n",
276 __FUNCTION__, g_reset_n_gpio, g_edge_wakeup_gpio, g_vdd_3v3_gpio);
277
278 vdd_3v3 = regulator_get(dev, "vdd33");
279 if (IS_ERR_OR_NULL(vdd_3v3)) {
280 if (PTR_ERR(vdd_3v3) < 0) {
281 pr_info("%s: the regulator for vdd_3v3 not found\n", __func__);
282 }
283 } else {
284 info->vdd_3v3 = vdd_3v3;
285 }
286
287 return 0;
288
289out:
290 return -EINVAL;
291}
292#else
293static int nz3_slic_dt_init(struct device_node *np,
294 struct device *dev,
295 struct nz3_slic_info *info)
296{
297 return 0;
298}
299#endif
300
301/* nz3_slic_ctrl */
302static struct dentry *nz3_slic_ctrl = NULL;
303
304static ssize_t nz3_slic_ctrl_read(struct file *file, char __user *user_buf,
305 size_t count, loff_t *ppos)
306{
307
308 printk(KERN_INFO"%s/L%d.\n", __FUNCTION__, __LINE__);
309
310 return 0;
311}
312
313/*
314 *control command:
315 *
316 *Disable VDD 3V3: echo 0 > /sys/kernel/debug/nz3_slic_ctrl
317 *Enable VDD 3V3: echo 1 > /sys/kernel/debug/nz3_slic_ctrl
318 *
319 *
320 */
321static char msg[10];
322
323static ssize_t nz3_slic_ctrl_write(struct file *file,
324 const char __user *user_buf,
325 size_t count, loff_t *ppos)
326{
327 int ret = 0;
328 size_t tmp_count = 0;
329
330 printk(KERN_INFO"%s/L%d.\n", __FUNCTION__, __LINE__);
331
332 memset(msg, 0x00, sizeof(msg));
333 tmp_count = count;
334
335 if (tmp_count >= sizeof(msg)){
336 tmp_count = sizeof(msg) - 1;
337 }
338
339 /* copy the content from user space to kernel space */
340 ret = copy_from_user(msg, user_buf, tmp_count);
341 if (ret){
342 printk(KERN_ALERT"copy from user fail \n");
343 return -EFAULT;
344 }
345
346 switch (msg[0]){
347 case '0':/* input command# echo 0 > /sys/kernel/debug/nz3_slic_ctrl */
348 printk(KERN_INFO "input %c. \n", msg[0]);
349 if (g_vdd_3v3_gpio >= 0) {
350 gpio_direction_output(g_vdd_3v3_gpio, 0);
351 }
352 printk(KERN_INFO "Disable VDD 3V3 for ASR1826 New DKB.\n");
353 break;
354
355 case '1':/* input command# echo 1 > /sys/kernel/debug/nz3_slic_ctrl */
356 printk(KERN_INFO "input %c. \n", msg[0]);
357 if (g_vdd_3v3_gpio >= 0) {
358 gpio_direction_output(g_vdd_3v3_gpio, 1);
359 }
360 printk(KERN_INFO "Enable VDD 3V3 for ASR1826 New DKB.\n");
361 break;
362
363 case '2':/* input command# echo 2 > /sys/kernel/debug/nz3_slic_ctrl */
364 printk(KERN_INFO "input %c. \n", msg[0]);
365#ifdef DEBUG_FALCON_SLIC_RESET
366 if (cpu_is_asr1803()) {
367 falcon_config_MFPR_GPIO10();
368 }
369#endif
370 if (g_reset_n_gpio >= 0) {
371 gpio_direction_output(g_reset_n_gpio, 0);
372 gpio_set_value(g_reset_n_gpio, 0);
373 }
374 printk(KERN_INFO "low reset pin, g_reset_n_gpio=%d.\n", g_reset_n_gpio);
375 break;
376
377 case '3':/* input command# echo 3 > /sys/kernel/debug/nz3_slic_ctrl */
378 printk(KERN_INFO "input %c. \n", msg[0]);
379#ifdef DEBUG_FALCON_SLIC_RESET
380 if (cpu_is_asr1803()) {
381 falcon_config_MFPR_GPIO10();
382 }
383#endif
384 if (g_reset_n_gpio >= 0) {
385 gpio_direction_output(g_reset_n_gpio, 1);
386 gpio_set_value(g_reset_n_gpio, 1);
387 }
388 printk(KERN_INFO "high reset pin, g_reset_n_gpio=%d.\n", g_reset_n_gpio);
389 break;
390
391 default:/* input command# */
392 printk(KERN_INFO "input invalid. \n");
393 break;
394 }
395
396 return tmp_count;
397}
398
399static const struct file_operations nz3_slic_ctrl_ops = {
400 .owner = THIS_MODULE,
401 .open = simple_open,
402 .read = nz3_slic_ctrl_read,
403 .write = nz3_slic_ctrl_write,
404};
405
406static inline int nz3_slic_ctrl_debugfs_init(void)
407{
408
409 nz3_slic_ctrl = debugfs_create_file("nz3_slic_ctrl", S_IRUGO | S_IFREG,
410 NULL, NULL, &nz3_slic_ctrl_ops);
411
412 if (nz3_slic_ctrl == NULL) {
413 pr_err("create nz3_slic_ctrl debugfs error!\n");
414 return -ENOENT;
415 } else if (nz3_slic_ctrl == ERR_PTR(-ENODEV)) {
416 pr_err("CONFIG_DEBUG_FS is not enabled!\n");
417 return -ENOENT;
418 }
419
420 return 0;
421}
422
423static void nz3_slic_ctrl_debugfs_remove(void)
424{
425 if (NULL != nz3_slic_ctrl){
426 debugfs_remove_recursive(nz3_slic_ctrl);
427 }
428
429 return;
430}
431
432static int nz3_slic_probe(struct platform_device *pdev)
433{
434 struct nz3_slic_info *info = NULL;
435 struct pinctrl_state *pin_default_nz3_slic = NULL;
436
437 struct device_node *np = pdev->dev.of_node;
438 int ret;
439
440 printk(KERN_INFO "enter %s. \n", __FUNCTION__);
441
442 info = devm_kzalloc(&pdev->dev, sizeof(struct nz3_slic_info),
443 GFP_KERNEL);
444 if (!info)
445 return -ENOMEM;
446
447 memset(info, 0x00, sizeof(struct nz3_slic_info));
448 info->reset_n_gpio = -1;
449 info->edge_wakeup_gpio = -1;
450 info->vdd_3v3_gpio = -1;
451
452 g_nz3_slic_pinctrl = devm_pinctrl_get(&pdev->dev);
453 pin_default_nz3_slic = pinctrl_lookup_state(g_nz3_slic_pinctrl, "default");
454 pinctrl_select_state(g_nz3_slic_pinctrl, pin_default_nz3_slic);
455
456 if (IS_ENABLED(CONFIG_OF)) {
457 ret = nz3_slic_dt_init(np, &pdev->dev, info);
458 if (ret) {
459 dev_err(&pdev->dev, "SLIC probe failed!\n");
460 return ret;
461 }
462 } else {
463 dev_err(&pdev->dev, "SLIC Not support DT, exit!\n");
464 return -EINVAL;
465 }
466
467 info->dev = &pdev->dev;
468
469 if (info->reset_n_gpio >= 0) {
470 ret = devm_gpio_request(info->dev,
471 info->reset_n_gpio, "slic_rst");
472 if (ret) {
473 dev_err(info->dev,
474 "request gpio %d failed\n", info->reset_n_gpio);
475 return ret;
476 }
477 }
478
479 /* use nz3-slic as wakeup source */
480 device_init_wakeup(&pdev->dev, 1);
481
482 if (info->edge_wakeup_gpio >= 0) {
483 ret = request_mfp_edge_wakeup(info->edge_wakeup_gpio,
484 NULL, info, info->dev);
485 if (ret) {
486 dev_err(info->dev, "failed to request edge wakeup.\n");
487 remove_mfp_edge_wakeup(info->edge_wakeup_gpio);
488 return ret;
489 }
490 }
491
492 if (info->vdd_3v3_gpio >= 0) {
493 ret = devm_gpio_request(info->dev, info->vdd_3v3_gpio, "vdd_3v3");
494 if (ret) {
495 dev_err(info->dev, "request gpio %d failed\n", info->vdd_3v3_gpio);
496 return ret;
497 }
498 }
499
500 slic_power_on(info);
501 strncpy(info->chip_status, "on", 3);
502
503 platform_set_drvdata(pdev, info);
504
505 ret = sysfs_create_group(&pdev->dev.kobj, &slic_attr_group);
506 if (ret) {
507 dev_err(&pdev->dev, "SLIC create sysfs fail!\n");
508 return ret;
509 }
510
511 /* init debug tool */
512 nz3_slic_ctrl_debugfs_init();
513 return 0;
514}
515
516static int nz3_slic_remove(struct platform_device *pdev)
517{
518 printk(KERN_INFO "enter %s. \n", __FUNCTION__);
519
520 sysfs_remove_group(&pdev->dev.kobj, &slic_attr_group);
521
522 nz3_slic_ctrl_debugfs_remove();
523 return 0;
524}
525
526#ifdef CONFIG_OF
527static const struct of_device_id nz3_slic_dt_match[] = {
528 { .compatible = "asr,nz3-slic", },
529 {},
530};
531#endif
532
533static struct platform_driver nz3_slic_driver = {
534 .driver = {
535 .name = "nz3-slic",
536 .owner = THIS_MODULE,
537#ifdef CONFIG_OF
538 .of_match_table = of_match_ptr(nz3_slic_dt_match),
539#endif
540 },
541 .probe = nz3_slic_probe,
542 .remove = nz3_slic_remove,
543};
544
545static int nz3_slic_init(void)
546{
547 return platform_driver_register(&nz3_slic_driver);
548}
549
550static void nz3_slic_exit(void)
551{
552 platform_driver_unregister(&nz3_slic_driver);
553}
554module_init(nz3_slic_init);
555module_exit(nz3_slic_exit);
556
557MODULE_AUTHOR("Yu Zhang <zhangy@marvell.com>");
558MODULE_DESCRIPTION("driver for Marvell PXA1826 SLIC solution");
559MODULE_LICENSE("GPL v2");