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