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 9 #include <asm/mach-pic32/pic32.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 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 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 51 int pic32_enable_lcd(void) 52 { 53 return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(31), BIT(31)); 54 } 55 56 int pic32_disable_lcd(void) 57 { 58 return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(31), 0); 59 } 60 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 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 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 87 static u32 pic32_get_device_id(void) 88 { 89 return pic32_conf_get_reg_field(PIC32_DEVID, 0, 0x0fffffff); 90 } 91 92 static u32 pic32_get_device_version(void) 93 { 94 return pic32_conf_get_reg_field(PIC32_DEVID, 28, 0xf); 95 } 96 97 u32 pic32_get_boot_status(void) 98 { 99 return pic32_reset_status; 100 } 101 EXPORT_SYMBOL(pic32_get_boot_status); 102 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