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