[PATCH v3 1/2] pinctrl: at91-pio4: Implement the correct drive values for sama7g5
From: Ryan.Wanner
Date: Mon Feb 27 2023 - 13:08:28 EST
From: Ryan Wanner <Ryan.Wanner@xxxxxxxxxxxxx>
Sama7g5 drive strength options have been updated from previous pio4
products. Now values will correctly align with sama7g5 drive strength
options highlighted in the sama7g5 data sheet.
Add xlate to separate the sama7g5 drive values and the sama5d27
drive values.
Signed-off-by: Ryan Wanner <Ryan.Wanner@xxxxxxxxxxxxx>
---
changes since v2:
-Add sama7g5 differences to dbg_show.
-Remove array length for xlate.
drivers/pinctrl/pinctrl-at91-pio4.c | 54 ++++++++++++++++++++++++++---
1 file changed, 49 insertions(+), 5 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index 82b921fd630d..76af50d62404 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -72,17 +72,33 @@
/* Custom pinconf parameters */
#define ATMEL_PIN_CONFIG_DRIVE_STRENGTH (PIN_CONFIG_END + 1)
+static const unsigned int drive_strength_xlate_sama7g5[] = {
+ ATMEL_PIO_DRVSTR_LO_D,
+ ATMEL_PIO_DRVSTR_HI_A,
+ ATMEL_PIO_DRVSTR_LO_C,
+ ATMEL_PIO_DRVSTR_LO_B
+};
+
+static const unsigned int drive_strength_xlate_sama5d2[] = {
+ ATMEL_PIO_DRVSTR_LO,
+ ATMEL_PIO_DRVSTR_LO_1,
+ ATMEL_PIO_DRVSTR_ME,
+ ATMEL_PIO_DRVSTR_HI
+};
+
/**
* struct atmel_pioctrl_data - Atmel PIO controller (pinmux + gpio) data struct
* @nbanks: number of PIO banks
* @last_bank_count: number of lines in the last bank (can be less than
* the rest of the banks).
* @slew_rate_support: slew rate support
+ * @drv_stre_xlate: xlate for different drive values
*/
struct atmel_pioctrl_data {
unsigned int nbanks;
unsigned int last_bank_count;
unsigned int slew_rate_support;
+ const unsigned int *drv_stre_xlate;
};
struct atmel_group {
@@ -121,6 +137,7 @@ struct atmel_pin {
* @dev: device entry for the Atmel PIO controller.
* @node: node of the Atmel PIO controller.
* @slew_rate_support: slew rate support
+ * @drv_stre_xlate: xlate for different drive values
*/
struct atmel_pioctrl {
void __iomem *reg_base;
@@ -143,6 +160,7 @@ struct atmel_pioctrl {
struct device *dev;
struct device_node *node;
unsigned int slew_rate_support;
+ const unsigned int *drv_stre_xlate;
};
static const char * const atmel_functions[] = {
@@ -872,12 +890,17 @@ static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
conf &= ~ATMEL_PIO_SR_MASK;
break;
case ATMEL_PIN_CONFIG_DRIVE_STRENGTH:
+ if (arg > ATMEL_PIO_DRVSTR_HI || arg < ATMEL_PIO_DRVSTR_LO) {
+ dev_warn(pctldev->dev, "drive strength not updated (incorrect value)\n");
+ break;
+ }
switch (arg) {
case ATMEL_PIO_DRVSTR_LO:
+ case ATMEL_PIO_DRVSTR_LO_1:
case ATMEL_PIO_DRVSTR_ME:
case ATMEL_PIO_DRVSTR_HI:
conf &= (~ATMEL_PIO_DRVSTR_MASK);
- conf |= arg << ATMEL_PIO_DRVSTR_OFFSET;
+ conf |= atmel_pioctrl->drv_stre_xlate[arg] << ATMEL_PIO_DRVSTR_OFFSET;
break;
default:
dev_warn(pctldev->dev, "drive strength not updated (incorrect value)\n");
@@ -903,6 +926,8 @@ static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev,
{
struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev);
u32 conf;
+ unsigned int arg;
+ u8 is_sama7 = atmel_pioctrl->drv_stre_xlate == drive_strength_xlate_sama7g5;
if (!atmel_pioctrl->pins[pin_id]->device)
return;
@@ -926,16 +951,32 @@ static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev,
if (atmel_pioctrl->slew_rate_support && (conf & ATMEL_PIO_SR_MASK))
seq_printf(s, "%s ", "slew-rate");
if (conf & ATMEL_PIO_DRVSTR_MASK) {
- switch ((conf & ATMEL_PIO_DRVSTR_MASK) >> ATMEL_PIO_DRVSTR_OFFSET) {
+ arg = (conf & ATMEL_PIO_DRVSTR_MASK) >> ATMEL_PIO_DRVSTR_OFFSET;
+ switch (atmel_pioctrl->drv_stre_xlate[arg]) {
case ATMEL_PIO_DRVSTR_ME:
- seq_printf(s, "%s ", "medium-drive");
+ if (is_sama7)
+ seq_printf(s, "%s ", "low-drive-typeD");
+ else
+ seq_printf(s, "%s ", "medium-drive");
break;
case ATMEL_PIO_DRVSTR_HI:
- seq_printf(s, "%s ", "high-drive");
+ if (is_sama7)
+ seq_printf(s, "%s ", "low-drive-typeB");
+ else
+ seq_printf(s, "%s ", "high-drive");
+ break;
+ case ATMEL_PIO_DRVSTR_HI_A:
+ if (is_sama7)
+ seq_printf(s, "%s ", "high-drive-typeA");
+ else
+ seq_printf(s, "%s ", "low-drive");
break;
/* ATMEL_PIO_DRVSTR_LO and 0 which is the default value at reset */
default:
- seq_printf(s, "%s ", "low-drive");
+ if (is_sama7)
+ seq_printf(s, "%s ", "low-drive-typeD");
+ else
+ seq_printf(s, "%s ", "low-drive");
}
}
}
@@ -1013,12 +1054,14 @@ static const struct dev_pm_ops atmel_pctrl_pm_ops = {
static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = {
.nbanks = 4,
.last_bank_count = ATMEL_PIO_NPINS_PER_BANK,
+ .drv_stre_xlate = drive_strength_xlate_sama5d2,
};
static const struct atmel_pioctrl_data microchip_sama7g5_pioctrl_data = {
.nbanks = 5,
.last_bank_count = 8, /* sama7g5 has only PE0 to PE7 */
.slew_rate_support = 1,
+ .drv_stre_xlate = drive_strength_xlate_sama7g5,
};
static const struct of_device_id atmel_pctrl_of_match[] = {
@@ -1064,6 +1107,7 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
atmel_pioctrl->npins += atmel_pioctrl_data->last_bank_count;
}
atmel_pioctrl->slew_rate_support = atmel_pioctrl_data->slew_rate_support;
+ atmel_pioctrl->drv_stre_xlate = atmel_pioctrl_data->drv_stre_xlate;
atmel_pioctrl->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(atmel_pioctrl->reg_base))
--
2.37.2