| // SPDX-License-Identifier: GPL-2.0-only |
| /* |
| * Purna Chandra Mandal, purna.mandal@microchip.com |
| * Copyright (C) 2015 Microchip Technology Inc. All rights reserved. |
| */ |
| #include <linux/init.h> |
| #include <linux/io.h> |
| #include <linux/spinlock.h> |
| |
| #include <asm/mach-pic32/pic32.h> |
| |
| #include "pic32mzda.h" |
| |
| #define PIC32_CFGCON 0x0000 |
| #define PIC32_DEVID 0x0020 |
| #define PIC32_SYSKEY 0x0030 |
| #define PIC32_CFGEBIA 0x00c0 |
| #define PIC32_CFGEBIC 0x00d0 |
| #define PIC32_CFGCON2 0x00f0 |
| #define PIC32_RCON 0x1240 |
| |
| static void __iomem *pic32_conf_base; |
| static DEFINE_SPINLOCK(config_lock); |
| static u32 pic32_reset_status; |
| |
| static u32 pic32_conf_get_reg_field(u32 offset, u32 rshift, u32 mask) |
| { |
| u32 v; |
| |
| v = readl(pic32_conf_base + offset); |
| v >>= rshift; |
| v &= mask; |
| |
| return v; |
| } |
| |
| static u32 pic32_conf_modify_atomic(u32 offset, u32 mask, u32 set) |
| { |
| u32 v; |
| unsigned long flags; |
| |
| spin_lock_irqsave(&config_lock, flags); |
| v = readl(pic32_conf_base + offset); |
| v &= ~mask; |
| v |= (set & mask); |
| writel(v, pic32_conf_base + offset); |
| spin_unlock_irqrestore(&config_lock, flags); |
| |
| return 0; |
| } |
| |
| int pic32_enable_lcd(void) |
| { |
| return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(31), BIT(31)); |
| } |
| |
| int pic32_disable_lcd(void) |
| { |
| return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(31), 0); |
| } |
| |
| int pic32_set_lcd_mode(int mode) |
| { |
| u32 mask = mode ? BIT(30) : 0; |
| |
| return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(30), mask); |
| } |
| |
| int pic32_set_sdhci_adma_fifo_threshold(u32 rthrsh, u32 wthrsh) |
| { |
| u32 clr, set; |
| |
| clr = (0x3ff << 4) | (0x3ff << 16); |
| set = (rthrsh << 4) | (wthrsh << 16); |
| return pic32_conf_modify_atomic(PIC32_CFGCON2, clr, set); |
| } |
| |
| void pic32_syskey_unlock_debug(const char *func, const ulong line) |
| { |
| void __iomem *syskey = pic32_conf_base + PIC32_SYSKEY; |
| |
| pr_debug("%s: called from %s:%lu\n", __func__, func, line); |
| writel(0x00000000, syskey); |
| writel(0xAA996655, syskey); |
| writel(0x556699AA, syskey); |
| } |
| |
| static u32 pic32_get_device_id(void) |
| { |
| return pic32_conf_get_reg_field(PIC32_DEVID, 0, 0x0fffffff); |
| } |
| |
| static u32 pic32_get_device_version(void) |
| { |
| return pic32_conf_get_reg_field(PIC32_DEVID, 28, 0xf); |
| } |
| |
| u32 pic32_get_boot_status(void) |
| { |
| return pic32_reset_status; |
| } |
| EXPORT_SYMBOL(pic32_get_boot_status); |
| |
| void __init pic32_config_init(void) |
| { |
| pic32_conf_base = ioremap(PIC32_BASE_CONFIG, 0x110); |
| if (!pic32_conf_base) |
| panic("pic32: config base not mapped"); |
| |
| /* Boot Status */ |
| pic32_reset_status = readl(pic32_conf_base + PIC32_RCON); |
| writel(-1, PIC32_CLR(pic32_conf_base + PIC32_RCON)); |
| |
| /* Device Information */ |
| pr_info("Device Id: 0x%08x, Device Ver: 0x%04x\n", |
| pic32_get_device_id(), |
| pic32_get_device_version()); |
| } |