Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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)  * linux/arch/arm/plat-pxa/mfp.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *   Multi-Function Pin Support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Copyright (C) 2007 Marvell Internation Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * 2007-08-21: eric miao <eric.miao@marvell.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *             initial version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <plat/mfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #define MFPR_SIZE	(PAGE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) /* MFPR register bit definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define MFPR_PULL_SEL		(0x1 << 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define MFPR_PULLUP_EN		(0x1 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define MFPR_PULLDOWN_EN	(0x1 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define MFPR_SLEEP_SEL		(0x1 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define MFPR_SLEEP_OE_N		(0x1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define MFPR_EDGE_CLEAR		(0x1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define MFPR_EDGE_FALL_EN	(0x1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define MFPR_EDGE_RISE_EN	(0x1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define MFPR_SLEEP_DATA(x)	((x) << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define MFPR_DRIVE(x)		(((x) & 0x7) << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define MFPR_AF_SEL(x)		(((x) & 0x7) << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define MFPR_EDGE_NONE		(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define MFPR_EDGE_RISE		(MFPR_EDGE_RISE_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define MFPR_EDGE_FALL		(MFPR_EDGE_FALL_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define MFPR_EDGE_BOTH		(MFPR_EDGE_RISE | MFPR_EDGE_FALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  * Table that determines the low power modes outputs, with actual settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  * used in parentheses for don't-care values. Except for the float output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  * the configured driven and pulled levels match, so if there is a need for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  * non-LPM pulled output, the same configuration could probably be used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * Output value  sleep_oe_n  sleep_data  pullup_en  pulldown_en  pull_sel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  *                 (bit 7)    (bit 8)    (bit 14)     (bit 13)   (bit 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * Input            0          X(0)        X(0)        X(0)       0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * Drive 0          0          0           0           X(1)       0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  * Drive 1          0          1           X(1)        0	  0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * Pull hi (1)      1          X(1)        1           0	  0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * Pull lo (0)      1          X(0)        0           1	  0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * Z (float)        1          X(0)        0           0	  0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) #define MFPR_LPM_INPUT		(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) #define MFPR_LPM_DRIVE_LOW	(MFPR_SLEEP_DATA(0) | MFPR_PULLDOWN_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) #define MFPR_LPM_DRIVE_HIGH    	(MFPR_SLEEP_DATA(1) | MFPR_PULLUP_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) #define MFPR_LPM_PULL_LOW      	(MFPR_LPM_DRIVE_LOW  | MFPR_SLEEP_OE_N)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) #define MFPR_LPM_PULL_HIGH     	(MFPR_LPM_DRIVE_HIGH | MFPR_SLEEP_OE_N)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) #define MFPR_LPM_FLOAT         	(MFPR_SLEEP_OE_N)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) #define MFPR_LPM_MASK		(0xe080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * The pullup and pulldown state of the MFP pin at run mode is by default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * determined by the selected alternate function. In case that some buggy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * devices need to override this default behavior,  the definitions below
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  * indicates the setting of corresponding MFPR bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * Definition       pull_sel  pullup_en  pulldown_en
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  * MFPR_PULL_NONE       0         0        0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * MFPR_PULL_LOW        1         0        1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * MFPR_PULL_HIGH       1         1        0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * MFPR_PULL_BOTH       1         1        1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  * MFPR_PULL_FLOAT	1         0        0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) #define MFPR_PULL_NONE		(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) #define MFPR_PULL_LOW		(MFPR_PULL_SEL | MFPR_PULLDOWN_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) #define MFPR_PULL_BOTH		(MFPR_PULL_LOW | MFPR_PULLUP_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) #define MFPR_PULL_HIGH		(MFPR_PULL_SEL | MFPR_PULLUP_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) #define MFPR_PULL_FLOAT		(MFPR_PULL_SEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) /* mfp_spin_lock is used to ensure that MFP register configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * (most likely a read-modify-write operation) is atomic, and that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * mfp_table[] is consistent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) static DEFINE_SPINLOCK(mfp_spin_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) static void __iomem *mfpr_mmio_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) struct mfp_pin {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	unsigned long	config;		/* -1 for not configured */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	unsigned long	mfpr_off;	/* MFPRxx Register offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	unsigned long	mfpr_run;	/* Run-Mode Register Value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	unsigned long	mfpr_lpm;	/* Low Power Mode Register Value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) static struct mfp_pin mfp_table[MFP_PIN_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static const unsigned long mfpr_lpm[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	MFPR_LPM_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	MFPR_LPM_DRIVE_LOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	MFPR_LPM_DRIVE_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	MFPR_LPM_PULL_LOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	MFPR_LPM_PULL_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	MFPR_LPM_FLOAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	MFPR_LPM_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static const unsigned long mfpr_pull[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	MFPR_PULL_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	MFPR_PULL_LOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	MFPR_PULL_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	MFPR_PULL_BOTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	MFPR_PULL_FLOAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static const unsigned long mfpr_edge[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	MFPR_EDGE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	MFPR_EDGE_RISE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	MFPR_EDGE_FALL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	MFPR_EDGE_BOTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define mfpr_readl(off)			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	__raw_readl(mfpr_mmio_base + (off))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define mfpr_writel(off, val)		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	__raw_writel(val, mfpr_mmio_base + (off))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define mfp_configured(p)	((p)->config != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)  * perform a read-back of any valid MFPR register to make sure the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)  * previous writings are finished
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static unsigned long mfpr_off_readback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define mfpr_sync()	(void)__raw_readl(mfpr_mmio_base + mfpr_off_readback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static inline void __mfp_config_run(struct mfp_pin *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	if (mfp_configured(p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		mfpr_writel(p->mfpr_off, p->mfpr_run);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static inline void __mfp_config_lpm(struct mfp_pin *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	if (mfp_configured(p)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		if (mfpr_clr != p->mfpr_run)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 			mfpr_writel(p->mfpr_off, mfpr_clr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		if (p->mfpr_lpm != mfpr_clr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 			mfpr_writel(p->mfpr_off, p->mfpr_lpm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) void mfp_config(unsigned long *mfp_cfgs, int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	spin_lock_irqsave(&mfp_spin_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	for (i = 0; i < num; i++, mfp_cfgs++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		unsigned long tmp, c = *mfp_cfgs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		struct mfp_pin *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		int pin, af, drv, lpm, edge, pull;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		pin = MFP_PIN(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		BUG_ON(pin >= MFP_PIN_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		p = &mfp_table[pin];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		af  = MFP_AF(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		drv = MFP_DS(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		lpm = MFP_LPM_STATE(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		edge = MFP_LPM_EDGE(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		pull = MFP_PULL(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		/* run-mode pull settings will conflict with MFPR bits of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		 * low power mode state,  calculate mfpr_run and mfpr_lpm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		 * individually if pull != MFP_PULL_NONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		if (likely(pull == MFP_PULL_NONE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 			p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 			p->mfpr_lpm = p->mfpr_run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 			p->mfpr_run = tmp | mfpr_pull[pull];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		p->config = c; __mfp_config_run(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	mfpr_sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	spin_unlock_irqrestore(&mfp_spin_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) unsigned long mfp_read(int mfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	unsigned long val, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	BUG_ON(mfp < 0 || mfp >= MFP_PIN_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	spin_lock_irqsave(&mfp_spin_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	val = mfpr_readl(mfp_table[mfp].mfpr_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	spin_unlock_irqrestore(&mfp_spin_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) void mfp_write(int mfp, unsigned long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	BUG_ON(mfp < 0 || mfp >= MFP_PIN_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	spin_lock_irqsave(&mfp_spin_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	mfpr_writel(mfp_table[mfp].mfpr_off, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	mfpr_sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	spin_unlock_irqrestore(&mfp_spin_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) void __init mfp_init_base(void __iomem *mfpr_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	/* initialize the table with default - unconfigured */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	for (i = 0; i < ARRAY_SIZE(mfp_table); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		mfp_table[i].config = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	mfpr_mmio_base = mfpr_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) void __init mfp_init_addr(struct mfp_addr_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	struct mfp_addr_map *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	unsigned long offset, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	spin_lock_irqsave(&mfp_spin_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	/* mfp offset for readback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	mfpr_off_readback = map[0].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	for (p = map; p->start != MFP_PIN_INVALID; p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		offset = p->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		i = p->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 			mfp_table[i].mfpr_off = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 			mfp_table[i].mfpr_run = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 			mfp_table[i].mfpr_lpm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 			offset += 4; i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		} while ((i <= p->end) && (p->end != -1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	spin_unlock_irqrestore(&mfp_spin_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) void mfp_config_lpm(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	struct mfp_pin *p = &mfp_table[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	int pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		__mfp_config_lpm(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) void mfp_config_run(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	struct mfp_pin *p = &mfp_table[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	int pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		__mfp_config_run(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }