Commit 7d29ed88 authored by Andrew Jeffery's avatar Andrew Jeffery Committed by Linus Walleij

pinctrl: aspeed: Read and write bits in LPC and GFX controllers

The System Control Unit IP block in the Aspeed SoCs is typically where
the pinmux configuration is found, but not always. A number of pins
depend on state in one of LPC Host Control (LHC) or SoC Display
Controller (GFX) IP blocks, so the Aspeed pinmux drivers should have the
means to adjust these as necessary.

We use syscon to cast a regmap over the GFX and LPC blocks, which is
used as an arbitration layer between the relevant driver and the pinctrl
subsystem. The regmaps are then exposed to the SoC-specific pinctrl
drivers by phandles in the devicetree, and are selected during a mux
request by querying a new 'ip' member in struct aspeed_sig_desc.
Signed-off-by: default avatarAndrew Jeffery <andrew@aj.id.au>
Reviewed-by: default avatarJoel Stanley <joel@jms.id.au>
Acked-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent c95b0fec
======================
Aspeed Pin Controllers
----------------------
======================
The Aspeed SoCs vary in functionality inside a generation but have a common mux
device register layout.
Required properties:
- compatible : Should be any one of the following:
"aspeed,ast2400-pinctrl"
"aspeed,g4-pinctrl"
"aspeed,ast2500-pinctrl"
"aspeed,g5-pinctrl"
Required properties for g4:
- compatible : Should be one of the following:
"aspeed,ast2400-pinctrl"
"aspeed,g4-pinctrl"
Required properties for g5:
- compatible : Should be one of the following:
"aspeed,ast2500-pinctrl"
"aspeed,g5-pinctrl"
- aspeed,external-nodes: A cell of phandles to external controller nodes:
0: compatible with "aspeed,ast2500-gfx", "syscon"
1: compatible with "aspeed,ast2500-lhc", "syscon"
The pin controller node should be the child of a syscon node with the required
property:
......@@ -24,7 +32,7 @@ Refer to the the bindings described in
Documentation/devicetree/bindings/mfd/syscon.txt
Subnode Format
--------------
==============
The required properties of child nodes are (as defined in pinctrl-bindings):
- function
......@@ -51,8 +59,11 @@ I2C9 MAC1LINK MDIO1 MDIO2 OSCCLK PEWAKE PWM0 PWM1 PWM2 PWM3 PWM4 PWM5 PWM6 PWM7
RGMII1 RGMII2 RMII1 RMII2 SD1 SPI1 SPI1DEBUG SPI1PASSTHRU TIMER4 TIMER5 TIMER6
TIMER7 TIMER8 VGABIOSROM
Examples
========
Examples:
g4 Example
----------
syscon: scu@1e6e2000 {
compatible = "aspeed,ast2400-scu", "syscon", "simple-mfd";
......@@ -68,5 +79,56 @@ syscon: scu@1e6e2000 {
};
};
g5 Example
----------
ahb {
apb {
syscon: scu@1e6e2000 {
compatible = "aspeed,ast2500-scu", "syscon", "simple-mfd";
reg = <0x1e6e2000 0x1a8>;
pinctrl: pinctrl {
compatible = "aspeed,g5-pinctrl";
aspeed,external-nodes = <&gfx &lhc>;
pinctrl_i2c3_default: i2c3_default {
function = "I2C3";
groups = "I2C3";
};
};
};
gfx: display@1e6e6000 {
compatible = "aspeed,ast2500-gfx", "syscon";
reg = <0x1e6e6000 0x1000>;
};
};
lpc: lpc@1e789000 {
compatible = "aspeed,ast2500-lpc", "simple-mfd";
reg = <0x1e789000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x1e789000 0x1000>;
lpc_host: lpc-host@80 {
compatible = "aspeed,ast2500-lpc-host", "simple-mfd", "syscon";
reg = <0x80 0x1e0>;
reg-io-width = <4>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x80 0x1e0>;
lhc: lhc@20 {
compatible = "aspeed,ast2500-lhc";
reg = <0x20 0x24 0x48 0x8>;
};
};
};
};
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices.
......@@ -292,7 +292,7 @@ SSSF_PIN_DECL(U18, GPIOG7, FLWP, SIG_DESC_SET(SCU84, 7));
#define UART6_DESC SIG_DESC_SET(SCU90, 7)
#define ROM16_DESC SIG_DESC_SET(SCU90, 6)
#define FLASH_WIDE SIG_DESC_SET(HW_STRAP1, 4)
#define BOOT_SRC_NOR { HW_STRAP1, GENMASK(1, 0), 0, 0 }
#define BOOT_SRC_NOR { ASPEED_IP_SCU, HW_STRAP1, GENMASK(1, 0), 0, 0 }
#define A8 56
SIG_EXPR_DECL(ROMD8, ROM16, ROM16_DESC);
......@@ -418,9 +418,9 @@ FUNC_GROUP_DECL(I2C8, G5, F3);
#define U1 88
SSSF_PIN_DECL(U1, GPIOL0, NCTS1, SIG_DESC_SET(SCU84, 16));
#define VPI18_DESC { SCU90, GENMASK(5, 4), 1, 0 }
#define VPI24_DESC { SCU90, GENMASK(5, 4), 2, 0 }
#define VPI30_DESC { SCU90, GENMASK(5, 4), 3, 0 }
#define VPI18_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 1, 0 }
#define VPI24_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 2, 0 }
#define VPI30_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 3, 0 }
#define T5 89
#define T5_DESC SIG_DESC_SET(SCU84, 17)
......@@ -641,11 +641,11 @@ SSSF_PIN_DECL(Y22, GPIOR2, ROMCS3, SIG_DESC_SET(SCU88, 26));
#define U19 139
SSSF_PIN_DECL(U19, GPIOR3, ROMCS4, SIG_DESC_SET(SCU88, 27));
#define VPOOFF0_DESC { SCU94, GENMASK(1, 0), 0, 0 }
#define VPO12_DESC { SCU94, GENMASK(1, 0), 1, 0 }
#define VPO24_DESC { SCU94, GENMASK(1, 0), 2, 0 }
#define VPOOFF1_DESC { SCU94, GENMASK(1, 0), 3, 0 }
#define VPO_OFF_12 { SCU94, 0x2, 0, 0 }
#define VPOOFF0_DESC { ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 0, 0 }
#define VPO12_DESC { ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 1, 0 }
#define VPO24_DESC { ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 2, 0 }
#define VPOOFF1_DESC { ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 3, 0 }
#define VPO_OFF_12 { ASPEED_IP_SCU, SCU94, 0x2, 0, 0 }
#define VPO_24_OFF SIG_DESC_SET(SCU94, 1)
#define V21 140
......
......@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
......@@ -26,8 +27,8 @@
#define ASPEED_G5_NR_PINS 228
#define COND1 { SCU90, BIT(6), 0, 0 }
#define COND2 { SCU94, GENMASK(1, 0), 0, 0 }
#define COND1 { ASPEED_IP_SCU, SCU90, BIT(6), 0, 0 }
#define COND2 { ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 0, 0 }
#define B14 0
SSSF_PIN_DECL(B14, GPIOA0, MAC1LINK, SIG_DESC_SET(SCU80, 0));
......@@ -186,9 +187,12 @@ MS_PIN_DECL(C20, GPIOE1, NDCD3, GPIE0OUT);
FUNC_GROUP_DECL(GPIE0, B20, C20);
#define SPI1_DESC { HW_STRAP1, GENMASK(13, 12), 1, 0 }
#define SPI1DEBUG_DESC { HW_STRAP1, GENMASK(13, 12), 2, 0 }
#define SPI1PASSTHRU_DESC { HW_STRAP1, GENMASK(13, 12), 3, 0 }
#define SPI1_DESC \
{ ASPEED_IP_SCU, HW_STRAP1, GENMASK(13, 12), 1, 0 }
#define SPI1DEBUG_DESC \
{ ASPEED_IP_SCU, HW_STRAP1, GENMASK(13, 12), 2, 0 }
#define SPI1PASSTHRU_DESC \
{ ASPEED_IP_SCU, HW_STRAP1, GENMASK(13, 12), 3, 0 }
#define C18 64
SIG_EXPR_DECL(SYSCS, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
......@@ -325,10 +329,11 @@ SS_PIN_DECL(R1, GPIOK7, SDA8);
FUNC_GROUP_DECL(I2C8, P2, R1);
#define VPIOFF0_DESC { SCU90, GENMASK(5, 4), 0, 0 }
#define VPIOFF1_DESC { SCU90, GENMASK(5, 4), 1, 0 }
#define VPI24_DESC { SCU90, GENMASK(5, 4), 2, 0 }
#define VPIRSVD_DESC { SCU90, GENMASK(5, 4), 3, 0 }
#define VPIOFF0_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 0, 0 }
#define VPIOFF1_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 1, 0 }
#define VPI24_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 2, 0 }
#define VPIRSVD_DESC { ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 3, 0 }
#define V2 104
#define V2_DESC SIG_DESC_SET(SCU88, 0)
......@@ -848,10 +853,35 @@ static struct pinctrl_desc aspeed_g5_pinctrl_desc = {
static int aspeed_g5_pinctrl_probe(struct platform_device *pdev)
{
int i;
struct regmap *map;
struct device_node *node;
for (i = 0; i < ARRAY_SIZE(aspeed_g5_pins); i++)
aspeed_g5_pins[i].number = i;
node = of_parse_phandle(pdev->dev.of_node, "aspeed,external-nodes", 0);
map = syscon_node_to_regmap(node);
of_node_put(node);
if (IS_ERR(map)) {
dev_warn(&pdev->dev, "No GFX phandle found, some mux configurations may fail\n");
map = NULL;
}
aspeed_g5_pinctrl_data.maps[ASPEED_IP_GFX] = map;
node = of_parse_phandle(pdev->dev.of_node, "aspeed,external-nodes", 1);
if (node) {
map = syscon_node_to_regmap(node->parent);
if (IS_ERR(map)) {
dev_warn(&pdev->dev, "LHC parent is not a syscon, some mux configurations may fail\n");
map = NULL;
}
} else {
dev_warn(&pdev->dev, "No LHC phandle found, some mux configurations may fail\n");
map = NULL;
}
of_node_put(node);
aspeed_g5_pinctrl_data.maps[ASPEED_IP_LPC] = map;
return aspeed_pinctrl_probe(pdev, &aspeed_g5_pinctrl_desc,
&aspeed_g5_pinctrl_data);
}
......
This diff is collapsed.
......@@ -232,6 +232,11 @@
* group.
*/
#define ASPEED_IP_SCU 0
#define ASPEED_IP_GFX 1
#define ASPEED_IP_LPC 2
#define ASPEED_NR_PINMUX_IPS 3
/*
* The "Multi-function Pins Mapping and Control" table in the SoC datasheet
* references registers by the device/offset mnemonic. The register macros
......@@ -261,7 +266,9 @@
* A signal descriptor, which describes the register, bits and the
* enable/disable values that should be compared or written.
*
* @reg: The register offset from base in bytes
* @ip: The IP block identifier, used as an index into the regmap array in
* struct aspeed_pinctrl_data
* @reg: The register offset with respect to the base address of the IP block
* @mask: The mask to apply to the register. The lowest set bit of the mask is
* used to derive the shift value.
* @enable: The value that enables the function. Value should be in the LSBs,
......@@ -270,6 +277,7 @@
* LSBs, not at the position of the mask.
*/
struct aspeed_sig_desc {
unsigned int ip;
unsigned int reg;
u32 mask;
u32 enable;
......@@ -313,24 +321,30 @@ struct aspeed_pin_desc {
/* Macro hell */
#define SIG_DESC_IP_BIT(ip, reg, idx, val) \
{ ip, reg, BIT_MASK(idx), val, (((val) + 1) & 1) }
/**
* Short-hand macro for describing a configuration enabled by the state of one
* bit. The disable value is derived.
* Short-hand macro for describing an SCU descriptor enabled by the state of
* one bit. The disable value is derived.
*
* @reg: The signal's associated register, offset from base
* @idx: The signal's bit index in the register
* @val: The value (0 or 1) that enables the function
*/
#define SIG_DESC_BIT(reg, idx, val) \
{ reg, BIT_MASK(idx), val, (((val) + 1) & 1) }
SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, val)
#define SIG_DESC_IP_SET(ip, reg, idx) SIG_DESC_IP_BIT(ip, reg, idx, 1)
/**
* A further short-hand macro describing a configuration enabled with a set bit.
* A further short-hand macro expanding to an SCU descriptor enabled by a set
* bit.
*
* @reg: The configuration's associated register, offset from base
* @idx: The configuration's bit index in the register
* @reg: The register, offset from base
* @idx: The bit index in the register
*/
#define SIG_DESC_SET(reg, idx) SIG_DESC_BIT(reg, idx, 1)
#define SIG_DESC_SET(reg, idx) SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, 1)
#define SIG_DESC_LIST_SYM(sig, func) sig_descs_ ## sig ## _ ## func
#define SIG_DESC_LIST_DECL(sig, func, ...) \
......@@ -500,7 +514,7 @@ struct aspeed_pin_desc {
MS_PIN_DECL_(pin, SIG_EXPR_LIST_PTR(gpio))
struct aspeed_pinctrl_data {
struct regmap *map;
struct regmap *maps[ASPEED_NR_PINMUX_IPS];
const struct pinctrl_pin_desc *pins;
const unsigned int npins;
......
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