162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Purna Chandra Mandal, purna.mandal@microchip.com 462306a36Sopenharmony_ci * Copyright (C) 2015 Microchip Technology Inc. All rights reserved. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#include <linux/init.h> 762306a36Sopenharmony_ci#include <linux/io.h> 862306a36Sopenharmony_ci#include <linux/spinlock.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <asm/mach-pic32/pic32.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "pic32mzda.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define PIC32_CFGCON 0x0000 1562306a36Sopenharmony_ci#define PIC32_DEVID 0x0020 1662306a36Sopenharmony_ci#define PIC32_SYSKEY 0x0030 1762306a36Sopenharmony_ci#define PIC32_CFGEBIA 0x00c0 1862306a36Sopenharmony_ci#define PIC32_CFGEBIC 0x00d0 1962306a36Sopenharmony_ci#define PIC32_CFGCON2 0x00f0 2062306a36Sopenharmony_ci#define PIC32_RCON 0x1240 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic void __iomem *pic32_conf_base; 2362306a36Sopenharmony_cistatic DEFINE_SPINLOCK(config_lock); 2462306a36Sopenharmony_cistatic u32 pic32_reset_status; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic u32 pic32_conf_get_reg_field(u32 offset, u32 rshift, u32 mask) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci u32 v; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci v = readl(pic32_conf_base + offset); 3162306a36Sopenharmony_ci v >>= rshift; 3262306a36Sopenharmony_ci v &= mask; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci return v; 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic u32 pic32_conf_modify_atomic(u32 offset, u32 mask, u32 set) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci u32 v; 4062306a36Sopenharmony_ci unsigned long flags; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci spin_lock_irqsave(&config_lock, flags); 4362306a36Sopenharmony_ci v = readl(pic32_conf_base + offset); 4462306a36Sopenharmony_ci v &= ~mask; 4562306a36Sopenharmony_ci v |= (set & mask); 4662306a36Sopenharmony_ci writel(v, pic32_conf_base + offset); 4762306a36Sopenharmony_ci spin_unlock_irqrestore(&config_lock, flags); 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci return 0; 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciint pic32_enable_lcd(void) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(31), BIT(31)); 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ciint pic32_disable_lcd(void) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(31), 0); 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ciint pic32_set_lcd_mode(int mode) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci u32 mask = mode ? BIT(30) : 0; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(30), mask); 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ciint pic32_set_sdhci_adma_fifo_threshold(u32 rthrsh, u32 wthrsh) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci u32 clr, set; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci clr = (0x3ff << 4) | (0x3ff << 16); 7462306a36Sopenharmony_ci set = (rthrsh << 4) | (wthrsh << 16); 7562306a36Sopenharmony_ci return pic32_conf_modify_atomic(PIC32_CFGCON2, clr, set); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_civoid pic32_syskey_unlock_debug(const char *func, const ulong line) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci void __iomem *syskey = pic32_conf_base + PIC32_SYSKEY; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci pr_debug("%s: called from %s:%lu\n", __func__, func, line); 8362306a36Sopenharmony_ci writel(0x00000000, syskey); 8462306a36Sopenharmony_ci writel(0xAA996655, syskey); 8562306a36Sopenharmony_ci writel(0x556699AA, syskey); 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic u32 pic32_get_device_id(void) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci return pic32_conf_get_reg_field(PIC32_DEVID, 0, 0x0fffffff); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic u32 pic32_get_device_version(void) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci return pic32_conf_get_reg_field(PIC32_DEVID, 28, 0xf); 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ciu32 pic32_get_boot_status(void) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci return pic32_reset_status; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ciEXPORT_SYMBOL(pic32_get_boot_status); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_civoid __init pic32_config_init(void) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci pic32_conf_base = ioremap(PIC32_BASE_CONFIG, 0x110); 10762306a36Sopenharmony_ci if (!pic32_conf_base) 10862306a36Sopenharmony_ci panic("pic32: config base not mapped"); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci /* Boot Status */ 11162306a36Sopenharmony_ci pic32_reset_status = readl(pic32_conf_base + PIC32_RCON); 11262306a36Sopenharmony_ci writel(-1, PIC32_CLR(pic32_conf_base + PIC32_RCON)); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci /* Device Information */ 11562306a36Sopenharmony_ci pr_info("Device Id: 0x%08x, Device Ver: 0x%04x\n", 11662306a36Sopenharmony_ci pic32_get_device_id(), 11762306a36Sopenharmony_ci pic32_get_device_version()); 11862306a36Sopenharmony_ci} 119