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