1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Purna Chandra Mandal, purna.mandal@microchip.com
4 * Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
5 */
6 #include <linux/init.h>
7 #include <linux/io.h>
8 #include <linux/platform_data/pic32.h>
9 #include <linux/spinlock.h>
10
11 #include "pic32mzda.h"
12
13 #define PIC32_CFGCON 0x0000
14 #define PIC32_DEVID 0x0020
15 #define PIC32_SYSKEY 0x0030
16 #define PIC32_CFGEBIA 0x00c0
17 #define PIC32_CFGEBIC 0x00d0
18 #define PIC32_CFGCON2 0x00f0
19 #define PIC32_RCON 0x1240
20
21 static void __iomem *pic32_conf_base;
22 static DEFINE_SPINLOCK(config_lock);
23 static u32 pic32_reset_status;
24
pic32_conf_get_reg_field(u32 offset,u32 rshift,u32 mask)25 static u32 pic32_conf_get_reg_field(u32 offset, u32 rshift, u32 mask)
26 {
27 u32 v;
28
29 v = readl(pic32_conf_base + offset);
30 v >>= rshift;
31 v &= mask;
32
33 return v;
34 }
35
pic32_conf_modify_atomic(u32 offset,u32 mask,u32 set)36 static u32 pic32_conf_modify_atomic(u32 offset, u32 mask, u32 set)
37 {
38 u32 v;
39 unsigned long flags;
40
41 spin_lock_irqsave(&config_lock, flags);
42 v = readl(pic32_conf_base + offset);
43 v &= ~mask;
44 v |= (set & mask);
45 writel(v, pic32_conf_base + offset);
46 spin_unlock_irqrestore(&config_lock, flags);
47
48 return 0;
49 }
50
pic32_enable_lcd(void)51 int pic32_enable_lcd(void)
52 {
53 return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(31), BIT(31));
54 }
55
pic32_disable_lcd(void)56 int pic32_disable_lcd(void)
57 {
58 return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(31), 0);
59 }
60
pic32_set_lcd_mode(int mode)61 int pic32_set_lcd_mode(int mode)
62 {
63 u32 mask = mode ? BIT(30) : 0;
64
65 return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(30), mask);
66 }
67
pic32_set_sdhci_adma_fifo_threshold(u32 rthrsh,u32 wthrsh)68 int pic32_set_sdhci_adma_fifo_threshold(u32 rthrsh, u32 wthrsh)
69 {
70 u32 clr, set;
71
72 clr = (0x3ff << 4) | (0x3ff << 16);
73 set = (rthrsh << 4) | (wthrsh << 16);
74 return pic32_conf_modify_atomic(PIC32_CFGCON2, clr, set);
75 }
76
pic32_syskey_unlock_debug(const char * func,const ulong line)77 void pic32_syskey_unlock_debug(const char *func, const ulong line)
78 {
79 void __iomem *syskey = pic32_conf_base + PIC32_SYSKEY;
80
81 pr_debug("%s: called from %s:%lu\n", __func__, func, line);
82 writel(0x00000000, syskey);
83 writel(0xAA996655, syskey);
84 writel(0x556699AA, syskey);
85 }
86
pic32_get_device_id(void)87 static u32 pic32_get_device_id(void)
88 {
89 return pic32_conf_get_reg_field(PIC32_DEVID, 0, 0x0fffffff);
90 }
91
pic32_get_device_version(void)92 static u32 pic32_get_device_version(void)
93 {
94 return pic32_conf_get_reg_field(PIC32_DEVID, 28, 0xf);
95 }
96
pic32_get_boot_status(void)97 u32 pic32_get_boot_status(void)
98 {
99 return pic32_reset_status;
100 }
101 EXPORT_SYMBOL(pic32_get_boot_status);
102
pic32_config_init(void)103 void __init pic32_config_init(void)
104 {
105 pic32_conf_base = ioremap(PIC32_BASE_CONFIG, 0x110);
106 if (!pic32_conf_base)
107 panic("pic32: config base not mapped");
108
109 /* Boot Status */
110 pic32_reset_status = readl(pic32_conf_base + PIC32_RCON);
111 writel(-1, PIC32_CLR(pic32_conf_base + PIC32_RCON));
112
113 /* Device Information */
114 pr_info("Device Id: 0x%08x, Device Ver: 0x%04x\n",
115 pic32_get_device_id(),
116 pic32_get_device_version());
117 }
118