Commit eb5c144c authored by Bjorn Andersson's avatar Bjorn Andersson Committed by Linus Walleij

pinctrl: qcom: spmi-mpp: Transpose pinmux function

The "function" of the MPP driver was inherited from the GPIO driver, but the
differences between the two hardware blocks makes both the driver and the
device tree binding to be awkward.

Instead of overloading the "normal" function with various modes this patch
transposes the pinmux function to represent the three operating modes of the
MPP (digital, analog and current sink). The properties of pin pairing and DTEST
routing is moved to separate properties.
Signed-off-by: default avatarBjorn Andersson <bjorn.andersson@sonymobile.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 099f3e4a
...@@ -77,12 +77,9 @@ to specify in a pin configuration subnode: ...@@ -77,12 +77,9 @@ to specify in a pin configuration subnode:
Value type: <string> Value type: <string>
Definition: Specify the alternative function to be configured for the Definition: Specify the alternative function to be configured for the
specified pins. Valid values are: specified pins. Valid values are:
"normal", "digital",
"paired", "analog",
"dtest1", "sink"
"dtest2",
"dtest3",
"dtest4"
- bias-disable: - bias-disable:
Usage: optional Usage: optional
...@@ -134,17 +131,11 @@ to specify in a pin configuration subnode: ...@@ -134,17 +131,11 @@ to specify in a pin configuration subnode:
defined in <dt-binding/pinctrl/qcom,pmic-mpp.h> defined in <dt-binding/pinctrl/qcom,pmic-mpp.h>
PMIC_MPP_AOUT_LVL_* PMIC_MPP_AOUT_LVL_*
- qcom,analog-mode: - qcom,dtest:
Usage: optional Usage: optional
Value type: <none> Value type: <u32>
Definition: Selects Analog mode of operation: combined with input-enable Definition: Selects which dtest rail to be routed in the various functions.
and/or output-high, output-low MPP could operate as Valid values are 1-4
Bidirectional Logic, Analog Input, Analog Output.
- qcom,sink-mode:
Usage: optional
Value type: <u32> or <none>
Definition: Selects sink mode of operation
- qcom,amux-route: - qcom,amux-route:
Usage: optional Usage: optional
...@@ -152,6 +143,10 @@ to specify in a pin configuration subnode: ...@@ -152,6 +143,10 @@ to specify in a pin configuration subnode:
Definition: Selects the source for analog input. Valid values are Definition: Selects the source for analog input. Valid values are
defined in <dt-bindings/pinctrl/qcom,pmic-mpp.h> defined in <dt-bindings/pinctrl/qcom,pmic-mpp.h>
PMIC_MPP_AMUX_ROUTE_CH5, PMIC_MPP_AMUX_ROUTE_CH6... PMIC_MPP_AMUX_ROUTE_CH5, PMIC_MPP_AMUX_ROUTE_CH6...
- qcom,paired:
Usage: optional
Value type: <none>
Definition: Indicates that the pin should be operating in paired mode.
Example: Example:
...@@ -168,7 +163,7 @@ Example: ...@@ -168,7 +163,7 @@ Example:
pm8841_default: default { pm8841_default: default {
gpio { gpio {
pins = "mpp1", "mpp2", "mpp3", "mpp4"; pins = "mpp1", "mpp2", "mpp3", "mpp4";
function = "normal"; function = "digital";
input-enable; input-enable;
power-source = <PM8841_MPP_S3>; power-source = <PM8841_MPP_S3>;
}; };
......
...@@ -95,13 +95,17 @@ ...@@ -95,13 +95,17 @@
#define PMIC_MPP_MODE_ANALOG_OUTPUT 5 #define PMIC_MPP_MODE_ANALOG_OUTPUT 5
#define PMIC_MPP_MODE_CURRENT_SINK 6 #define PMIC_MPP_MODE_CURRENT_SINK 6
#define PMIC_MPP_SELECTOR_NORMAL 0
#define PMIC_MPP_SELECTOR_PAIRED 1
#define PMIC_MPP_SELECTOR_DTEST_FIRST 4
#define PMIC_MPP_PHYSICAL_OFFSET 1 #define PMIC_MPP_PHYSICAL_OFFSET 1
/* Qualcomm specific pin configurations */ /* Qualcomm specific pin configurations */
#define PMIC_MPP_CONF_AMUX_ROUTE (PIN_CONFIG_END + 1) #define PMIC_MPP_CONF_AMUX_ROUTE (PIN_CONFIG_END + 1)
#define PMIC_MPP_CONF_ANALOG_MODE (PIN_CONFIG_END + 2) #define PMIC_MPP_CONF_ANALOG_LEVEL (PIN_CONFIG_END + 2)
#define PMIC_MPP_CONF_SINK_MODE (PIN_CONFIG_END + 3) #define PMIC_MPP_CONF_DTEST_SELECTOR (PIN_CONFIG_END + 3)
#define PMIC_MPP_CONF_ANALOG_LEVEL (PIN_CONFIG_END + 4) #define PMIC_MPP_CONF_PAIRED (PIN_CONFIG_END + 4)
/** /**
* struct pmic_mpp_pad - keep current MPP settings * struct pmic_mpp_pad - keep current MPP settings
...@@ -111,9 +115,7 @@ ...@@ -111,9 +115,7 @@
* @out_value: Cached pin output value. * @out_value: Cached pin output value.
* @output_enabled: Set to true if MPP output logic is enabled. * @output_enabled: Set to true if MPP output logic is enabled.
* @input_enabled: Set to true if MPP input buffer logic is enabled. * @input_enabled: Set to true if MPP input buffer logic is enabled.
* @analog_mode: Set to true when MPP should operate in Analog Input, Analog * @paired: Pin operates in paired mode
* Output or Bidirectional Analog mode.
* @sink_mode: Boolean indicating if ink mode is slected
* @num_sources: Number of power-sources supported by this MPP. * @num_sources: Number of power-sources supported by this MPP.
* @power_source: Current power-source used. * @power_source: Current power-source used.
* @amux_input: Set the source for analog input. * @amux_input: Set the source for analog input.
...@@ -121,6 +123,7 @@ ...@@ -121,6 +123,7 @@
* @pullup: Pullup resistor value. Valid in Bidirectional mode only. * @pullup: Pullup resistor value. Valid in Bidirectional mode only.
* @function: See pmic_mpp_functions[]. * @function: See pmic_mpp_functions[].
* @drive_strength: Amount of current in sink mode * @drive_strength: Amount of current in sink mode
* @dtest: DTEST route selector
*/ */
struct pmic_mpp_pad { struct pmic_mpp_pad {
u16 base; u16 base;
...@@ -129,8 +132,7 @@ struct pmic_mpp_pad { ...@@ -129,8 +132,7 @@ struct pmic_mpp_pad {
bool out_value; bool out_value;
bool output_enabled; bool output_enabled;
bool input_enabled; bool input_enabled;
bool analog_mode; bool paired;
bool sink_mode;
unsigned int num_sources; unsigned int num_sources;
unsigned int power_source; unsigned int power_source;
unsigned int amux_input; unsigned int amux_input;
...@@ -138,6 +140,7 @@ struct pmic_mpp_pad { ...@@ -138,6 +140,7 @@ struct pmic_mpp_pad {
unsigned int pullup; unsigned int pullup;
unsigned int function; unsigned int function;
unsigned int drive_strength; unsigned int drive_strength;
unsigned int dtest;
}; };
struct pmic_mpp_state { struct pmic_mpp_state {
...@@ -150,16 +153,16 @@ struct pmic_mpp_state { ...@@ -150,16 +153,16 @@ struct pmic_mpp_state {
static const struct pinconf_generic_params pmic_mpp_bindings[] = { static const struct pinconf_generic_params pmic_mpp_bindings[] = {
{"qcom,amux-route", PMIC_MPP_CONF_AMUX_ROUTE, 0}, {"qcom,amux-route", PMIC_MPP_CONF_AMUX_ROUTE, 0},
{"qcom,analog-level", PMIC_MPP_CONF_ANALOG_LEVEL, 0}, {"qcom,analog-level", PMIC_MPP_CONF_ANALOG_LEVEL, 0},
{"qcom,analog-mode", PMIC_MPP_CONF_ANALOG_MODE, 0}, {"qcom,dtest", PMIC_MPP_CONF_DTEST_SELECTOR, 0},
{"qcom,sink-mode", PMIC_MPP_CONF_SINK_MODE, 0}, {"qcom,paired", PMIC_MPP_CONF_PAIRED, 0},
}; };
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
static const struct pin_config_item pmic_conf_items[] = { static const struct pin_config_item pmic_conf_items[] = {
PCONFDUMP(PMIC_MPP_CONF_AMUX_ROUTE, "analog mux", NULL, true), PCONFDUMP(PMIC_MPP_CONF_AMUX_ROUTE, "analog mux", NULL, true),
PCONFDUMP(PMIC_MPP_CONF_ANALOG_LEVEL, "analog level", NULL, true), PCONFDUMP(PMIC_MPP_CONF_ANALOG_LEVEL, "analog level", NULL, true),
PCONFDUMP(PMIC_MPP_CONF_ANALOG_MODE, "analog output", NULL, false), PCONFDUMP(PMIC_MPP_CONF_DTEST_SELECTOR, "dtest", NULL, true),
PCONFDUMP(PMIC_MPP_CONF_SINK_MODE, "sink mode", NULL, false), PCONFDUMP(PMIC_MPP_CONF_PAIRED, "paired", NULL, false),
}; };
#endif #endif
...@@ -167,11 +170,12 @@ static const char *const pmic_mpp_groups[] = { ...@@ -167,11 +170,12 @@ static const char *const pmic_mpp_groups[] = {
"mpp1", "mpp2", "mpp3", "mpp4", "mpp5", "mpp6", "mpp7", "mpp8", "mpp1", "mpp2", "mpp3", "mpp4", "mpp5", "mpp6", "mpp7", "mpp8",
}; };
#define PMIC_MPP_DIGITAL 0
#define PMIC_MPP_ANALOG 1
#define PMIC_MPP_SINK 2
static const char *const pmic_mpp_functions[] = { static const char *const pmic_mpp_functions[] = {
PMIC_MPP_FUNC_NORMAL, PMIC_MPP_FUNC_PAIRED, "digital", "analog", "sink"
"reserved1", "reserved2",
PMIC_MPP_FUNC_DTEST1, PMIC_MPP_FUNC_DTEST2,
PMIC_MPP_FUNC_DTEST3, PMIC_MPP_FUNC_DTEST4,
}; };
static inline struct pmic_mpp_state *to_mpp_state(struct gpio_chip *chip) static inline struct pmic_mpp_state *to_mpp_state(struct gpio_chip *chip)
...@@ -260,31 +264,46 @@ static int pmic_mpp_get_function_groups(struct pinctrl_dev *pctldev, ...@@ -260,31 +264,46 @@ static int pmic_mpp_get_function_groups(struct pinctrl_dev *pctldev,
static int pmic_mpp_write_mode_ctl(struct pmic_mpp_state *state, static int pmic_mpp_write_mode_ctl(struct pmic_mpp_state *state,
struct pmic_mpp_pad *pad) struct pmic_mpp_pad *pad)
{ {
unsigned int mode;
unsigned int sel;
unsigned int val; unsigned int val;
unsigned int en;
if (pad->analog_mode) {
val = PMIC_MPP_MODE_ANALOG_INPUT; switch (pad->function) {
if (pad->output_enabled) { case PMIC_MPP_ANALOG:
if (pad->input_enabled) if (pad->input_enabled && pad->output_enabled)
val = PMIC_MPP_MODE_ANALOG_BIDIR; mode = PMIC_MPP_MODE_ANALOG_BIDIR;
else else if (pad->input_enabled)
val = PMIC_MPP_MODE_ANALOG_OUTPUT; mode = PMIC_MPP_MODE_ANALOG_INPUT;
} else
} else if (pad->sink_mode) { mode = PMIC_MPP_MODE_ANALOG_OUTPUT;
val = PMIC_MPP_MODE_CURRENT_SINK; break;
} else { case PMIC_MPP_DIGITAL:
val = PMIC_MPP_MODE_DIGITAL_INPUT; if (pad->input_enabled && pad->output_enabled)
if (pad->output_enabled) { mode = PMIC_MPP_MODE_DIGITAL_BIDIR;
if (pad->input_enabled) else if (pad->input_enabled)
val = PMIC_MPP_MODE_DIGITAL_BIDIR; mode = PMIC_MPP_MODE_DIGITAL_INPUT;
else else
val = PMIC_MPP_MODE_DIGITAL_OUTPUT; mode = PMIC_MPP_MODE_DIGITAL_OUTPUT;
} break;
case PMIC_MPP_SINK:
default:
mode = PMIC_MPP_MODE_CURRENT_SINK;
break;
} }
val = val << PMIC_MPP_REG_MODE_DIR_SHIFT; if (pad->dtest)
val |= pad->function << PMIC_MPP_REG_MODE_FUNCTION_SHIFT; sel = PMIC_MPP_SELECTOR_DTEST_FIRST + pad->dtest - 1;
val |= pad->out_value & PMIC_MPP_REG_MODE_VALUE_MASK; else if (pad->paired)
sel = PMIC_MPP_SELECTOR_PAIRED;
else
sel = PMIC_MPP_SELECTOR_NORMAL;
en = !!pad->out_value;
val = mode << PMIC_MPP_REG_MODE_DIR_SHIFT |
sel << PMIC_MPP_REG_MODE_FUNCTION_SHIFT |
en;
return pmic_mpp_write(state, pad, PMIC_MPP_REG_MODE_CTL, val); return pmic_mpp_write(state, pad, PMIC_MPP_REG_MODE_CTL, val);
} }
...@@ -358,21 +377,21 @@ static int pmic_mpp_config_get(struct pinctrl_dev *pctldev, ...@@ -358,21 +377,21 @@ static int pmic_mpp_config_get(struct pinctrl_dev *pctldev,
case PIN_CONFIG_OUTPUT: case PIN_CONFIG_OUTPUT:
arg = pad->out_value; arg = pad->out_value;
break; break;
case PMIC_MPP_CONF_DTEST_SELECTOR:
arg = pad->dtest;
break;
case PMIC_MPP_CONF_AMUX_ROUTE: case PMIC_MPP_CONF_AMUX_ROUTE:
arg = pad->amux_input; arg = pad->amux_input;
break; break;
case PMIC_MPP_CONF_PAIRED:
arg = pad->paired;
break;
case PIN_CONFIG_DRIVE_STRENGTH: case PIN_CONFIG_DRIVE_STRENGTH:
arg = pad->drive_strength; arg = pad->drive_strength;
break; break;
case PMIC_MPP_CONF_ANALOG_LEVEL: case PMIC_MPP_CONF_ANALOG_LEVEL:
arg = pad->aout_level; arg = pad->aout_level;
break; break;
case PMIC_MPP_CONF_ANALOG_MODE:
arg = pad->analog_mode;
break;
case PMIC_MPP_CONF_SINK_MODE:
arg = pad->sink_mode;
break;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -434,6 +453,9 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin, ...@@ -434,6 +453,9 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
pad->output_enabled = true; pad->output_enabled = true;
pad->out_value = arg; pad->out_value = arg;
break; break;
case PMIC_MPP_CONF_DTEST_SELECTOR:
pad->dtest = arg;
break;
case PIN_CONFIG_DRIVE_STRENGTH: case PIN_CONFIG_DRIVE_STRENGTH:
arg = pad->drive_strength; arg = pad->drive_strength;
break; break;
...@@ -445,11 +467,8 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin, ...@@ -445,11 +467,8 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
case PMIC_MPP_CONF_ANALOG_LEVEL: case PMIC_MPP_CONF_ANALOG_LEVEL:
pad->aout_level = arg; pad->aout_level = arg;
break; break;
case PMIC_MPP_CONF_ANALOG_MODE: case PMIC_MPP_CONF_PAIRED:
pad->analog_mode = !!arg; pad->paired = !!arg;
break;
case PMIC_MPP_CONF_SINK_MODE:
pad->sink_mode = !!arg;
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -498,10 +517,6 @@ static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev, ...@@ -498,10 +517,6 @@ static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev,
"0.6kOhm", "10kOhm", "30kOhm", "Disabled" "0.6kOhm", "10kOhm", "30kOhm", "Disabled"
}; };
static const char *const modes[] = {
"digital", "analog", "sink"
};
pad = pctldev->desc->pins[pin].drv_data; pad = pctldev->desc->pins[pin].drv_data;
seq_printf(s, " mpp%-2d:", pin + PMIC_MPP_PHYSICAL_OFFSET); seq_printf(s, " mpp%-2d:", pin + PMIC_MPP_PHYSICAL_OFFSET);
...@@ -520,12 +535,15 @@ static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev, ...@@ -520,12 +535,15 @@ static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev,
} }
seq_printf(s, " %-4s", pad->output_enabled ? "out" : "in"); seq_printf(s, " %-4s", pad->output_enabled ? "out" : "in");
seq_printf(s, " %-7s", modes[pad->analog_mode ? 1 : (pad->sink_mode ? 2 : 0)]);
seq_printf(s, " %-7s", pmic_mpp_functions[pad->function]); seq_printf(s, " %-7s", pmic_mpp_functions[pad->function]);
seq_printf(s, " vin-%d", pad->power_source); seq_printf(s, " vin-%d", pad->power_source);
seq_printf(s, " %d", pad->aout_level); seq_printf(s, " %d", pad->aout_level);
seq_printf(s, " %-8s", biases[pad->pullup]); seq_printf(s, " %-8s", biases[pad->pullup]);
seq_printf(s, " %-4s", pad->out_value ? "high" : "low"); seq_printf(s, " %-4s", pad->out_value ? "high" : "low");
if (pad->dtest)
seq_printf(s, " dtest%d", pad->dtest);
if (pad->paired)
seq_puts(s, " paired");
} }
} }
...@@ -646,6 +664,7 @@ static int pmic_mpp_populate(struct pmic_mpp_state *state, ...@@ -646,6 +664,7 @@ static int pmic_mpp_populate(struct pmic_mpp_state *state,
struct pmic_mpp_pad *pad) struct pmic_mpp_pad *pad)
{ {
int type, subtype, val, dir; int type, subtype, val, dir;
unsigned int sel;
type = pmic_mpp_read(state, pad, PMIC_MPP_REG_TYPE); type = pmic_mpp_read(state, pad, PMIC_MPP_REG_TYPE);
if (type < 0) if (type < 0)
...@@ -691,52 +710,50 @@ static int pmic_mpp_populate(struct pmic_mpp_state *state, ...@@ -691,52 +710,50 @@ static int pmic_mpp_populate(struct pmic_mpp_state *state,
case PMIC_MPP_MODE_DIGITAL_INPUT: case PMIC_MPP_MODE_DIGITAL_INPUT:
pad->input_enabled = true; pad->input_enabled = true;
pad->output_enabled = false; pad->output_enabled = false;
pad->analog_mode = false; pad->function = PMIC_MPP_DIGITAL;
pad->sink_mode = false;
break; break;
case PMIC_MPP_MODE_DIGITAL_OUTPUT: case PMIC_MPP_MODE_DIGITAL_OUTPUT:
pad->input_enabled = false; pad->input_enabled = false;
pad->output_enabled = true; pad->output_enabled = true;
pad->analog_mode = false; pad->function = PMIC_MPP_DIGITAL;
pad->sink_mode = false;
break; break;
case PMIC_MPP_MODE_DIGITAL_BIDIR: case PMIC_MPP_MODE_DIGITAL_BIDIR:
pad->input_enabled = true; pad->input_enabled = true;
pad->output_enabled = true; pad->output_enabled = true;
pad->analog_mode = false; pad->function = PMIC_MPP_DIGITAL;
pad->sink_mode = false;
break; break;
case PMIC_MPP_MODE_ANALOG_BIDIR: case PMIC_MPP_MODE_ANALOG_BIDIR:
pad->input_enabled = true; pad->input_enabled = true;
pad->output_enabled = true; pad->output_enabled = true;
pad->analog_mode = true; pad->function = PMIC_MPP_ANALOG;
pad->sink_mode = false;
break; break;
case PMIC_MPP_MODE_ANALOG_INPUT: case PMIC_MPP_MODE_ANALOG_INPUT:
pad->input_enabled = true; pad->input_enabled = true;
pad->output_enabled = false; pad->output_enabled = false;
pad->analog_mode = true; pad->function = PMIC_MPP_ANALOG;
pad->sink_mode = false;
break; break;
case PMIC_MPP_MODE_ANALOG_OUTPUT: case PMIC_MPP_MODE_ANALOG_OUTPUT:
pad->input_enabled = false; pad->input_enabled = false;
pad->output_enabled = true; pad->output_enabled = true;
pad->analog_mode = true; pad->function = PMIC_MPP_ANALOG;
pad->sink_mode = false;
break; break;
case PMIC_MPP_MODE_CURRENT_SINK: case PMIC_MPP_MODE_CURRENT_SINK:
pad->input_enabled = false; pad->input_enabled = false;
pad->output_enabled = true; pad->output_enabled = true;
pad->analog_mode = false; pad->function = PMIC_MPP_SINK;
pad->sink_mode = true;
break; break;
default: default:
dev_err(state->dev, "unknown MPP direction\n"); dev_err(state->dev, "unknown MPP direction\n");
return -ENODEV; return -ENODEV;
} }
pad->function = val >> PMIC_MPP_REG_MODE_FUNCTION_SHIFT; sel = val >> PMIC_MPP_REG_MODE_FUNCTION_SHIFT;
pad->function &= PMIC_MPP_REG_MODE_FUNCTION_MASK; sel &= PMIC_MPP_REG_MODE_FUNCTION_MASK;
if (sel >= PMIC_MPP_SELECTOR_DTEST_FIRST)
pad->dtest = sel + 1;
else if (sel == PMIC_MPP_SELECTOR_PAIRED)
pad->paired = true;
val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_VIN_CTL); val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_VIN_CTL);
if (val < 0) if (val < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment