1 /* 2 * Purna Chandra Mandal, purna.mandal@microchip.com 3 * Copyright (C) 2015 Microchip Technology Inc. All rights reserved. 4 * 5 * This program is free software; you can distribute it and/or modify it 6 * under the terms of the GNU General Public License (Version 2) as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * for more details. 13 */ 14 #include <linux/init.h> 15 #include <linux/io.h> 16 #include <linux/of_platform.h> 17 18 #include <asm/mach-pic32/pic32.h> 19 20 #include "pic32mzda.h" 21 22 #define PIC32_CFGCON 0x0000 23 #define PIC32_DEVID 0x0020 24 #define PIC32_SYSKEY 0x0030 25 #define PIC32_CFGEBIA 0x00c0 26 #define PIC32_CFGEBIC 0x00d0 27 #define PIC32_CFGCON2 0x00f0 28 #define PIC32_RCON 0x1240 29 30 static void __iomem *pic32_conf_base; 31 static DEFINE_SPINLOCK(config_lock); 32 static u32 pic32_reset_status; 33 34 static u32 pic32_conf_get_reg_field(u32 offset, u32 rshift, u32 mask) 35 { 36 u32 v; 37 38 v = readl(pic32_conf_base + offset); 39 v >>= rshift; 40 v &= mask; 41 42 return v; 43 } 44 45 static u32 pic32_conf_modify_atomic(u32 offset, u32 mask, u32 set) 46 { 47 u32 v; 48 unsigned long flags; 49 50 spin_lock_irqsave(&config_lock, flags); 51 v = readl(pic32_conf_base + offset); 52 v &= ~mask; 53 v |= (set & mask); 54 writel(v, pic32_conf_base + offset); 55 spin_unlock_irqrestore(&config_lock, flags); 56 57 return 0; 58 } 59 60 int pic32_enable_lcd(void) 61 { 62 return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(31), BIT(31)); 63 } 64 65 int pic32_disable_lcd(void) 66 { 67 return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(31), 0); 68 } 69 70 int pic32_set_lcd_mode(int mode) 71 { 72 u32 mask = mode ? BIT(30) : 0; 73 74 return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(30), mask); 75 } 76 77 int pic32_set_sdhci_adma_fifo_threshold(u32 rthrsh, u32 wthrsh) 78 { 79 u32 clr, set; 80 81 clr = (0x3ff << 4) | (0x3ff << 16); 82 set = (rthrsh << 4) | (wthrsh << 16); 83 return pic32_conf_modify_atomic(PIC32_CFGCON2, clr, set); 84 } 85 86 void pic32_syskey_unlock_debug(const char *func, const ulong line) 87 { 88 void __iomem *syskey = pic32_conf_base + PIC32_SYSKEY; 89 90 pr_debug("%s: called from %s:%lu\n", __func__, func, line); 91 writel(0x00000000, syskey); 92 writel(0xAA996655, syskey); 93 writel(0x556699AA, syskey); 94 } 95 96 static u32 pic32_get_device_id(void) 97 { 98 return pic32_conf_get_reg_field(PIC32_DEVID, 0, 0x0fffffff); 99 } 100 101 static u32 pic32_get_device_version(void) 102 { 103 return pic32_conf_get_reg_field(PIC32_DEVID, 28, 0xf); 104 } 105 106 u32 pic32_get_boot_status(void) 107 { 108 return pic32_reset_status; 109 } 110 EXPORT_SYMBOL(pic32_get_boot_status); 111 112 void __init pic32_config_init(void) 113 { 114 pic32_conf_base = ioremap(PIC32_BASE_CONFIG, 0x110); 115 if (!pic32_conf_base) 116 panic("pic32: config base not mapped"); 117 118 /* Boot Status */ 119 pic32_reset_status = readl(pic32_conf_base + PIC32_RCON); 120 writel(-1, PIC32_CLR(pic32_conf_base + PIC32_RCON)); 121 122 /* Device Inforation */ 123 pr_info("Device Id: 0x%08x, Device Ver: 0x%04x\n", 124 pic32_get_device_id(), 125 pic32_get_device_version()); 126 } 127