Memory controller drivers for v6.2, part two

1. ARM PL353: document PL354 in bindings.
 2. TI/OMAP GPMC: allow setting wait-pin polarity.
 -----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCgAuFiEE3dJiKD0RGyM7briowTdm5oaLg9cFAmN0rokQHGtyemtAa2Vy
 bmVsLm9yZwAKCRDBN2bmhouD15XSD/wJOuIEjIMwEs8M5i2PnXD4JGkG20tc22kj
 cD2RN9DRONeO4VQtDY73/DzZJ12JGRHIMU+UQkrvydef6WhGlKjyLPzFij1dSbVN
 PUmwM6jVMC0UjlEAaLnqfGYUZdhI1AAdZRowWTeDNhnTZ3G4MGpCe26shWXcZI0d
 cOkXAxcqmooh2wDmXAPzLcH49a5uOlmDKa3mwtqj5lpEKI/AQ1R8D4pqNIClPN8r
 oz7tDVGFnCo1MYZdY6k4o1K+Kut2M95phBbXB7Kl1+/tWg24loZGDUFPh/qBTXsF
 cpHAMwnmh+PPq5sRY8gtDqXA6WeawGpXYKBx9CRroRH5bUynqvNJkdWvKsIQyxpL
 w5waqwadMH+hoiXXI/ciqaX77geSzSCGfiQ0C66t823ubxC2gP/CS8y6K8FR7tLL
 srD0Kz4e1RaRV8e9Y+jgYkRV34ENmbztHTwMv/17wCjZs7MDDrQCV3fAmybnwDrW
 YHOvovnxETnfAFTK6M+cXBW5U0jbDzijGhr4CXDWlySBV4RClO4kga9fu2UNz9FM
 0Hn6EjxaT71KAKirUzxP5lumMrI6QCUpUHLoqTNRP6Gd6Y1AkgEJh2gnqF8QiphZ
 yg+JUy2Y59rg1kBgxFZxTZwull4UNVzG9MQ2JPGfSoRuUV6LZxc2OlH3dDr+MU+R
 ldgXWDKXwg==
 =NZo/
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmN7nsYACgkQmmx57+YA
 GNnsVRAAklSlSEtuLw2yumWvTE5trerQ5a1pFqy55WHKbySAlUU7I5J1/sER8FCy
 FW5V1IvDewUE94OgYqXQk4P6jrdN0h3MphK0MVfhxlfhlKO5TdZe+MGKR2gheK9+
 o6k28PP3xtKuC0VY4Qv/HdnPQ9Hq//BDHNUCvx9l960OQv198QqFxM5lGPCxJcL2
 JxIhRTuvZb37XgQgOtFMPLVPbApgSfWwoVwjkx+GFRe1Zuv9vjlEYPARlbJhSvXp
 FHmM+v7VxNQqSOwTB0yITtlXThHi28d8cM+FIxREBFlfkSVdUGjxVrEJjpFR7emV
 UOwdqxgmgpM5OjjkQwB2KHvulqHnq4pemQl9klaTY3Xwm7aKrFoaZf4XumNuo8gW
 kNJB89ODlMo/lutf0dB1MgSj6rSTqEoL3svqCmGhrPdjF0CH55l75QoyjIAq+67q
 A13YovG7nxngecE6qP4PFh3rBlUq51m5D0qLlA3diR5OaR77nsdXPLERSs3S9V8n
 s0FqFq3Hz/xZuUSXTweOQs9QF9BJZKv0VMb6flHpGHsB6+exmXBe4WXaJa5vv2iW
 o0u8AHtirposBPl5S/z7ecbzMEd4B0PRPzCHYAQ6t/vM6rbkZnYdynUb+QBH1+68
 yo7N4y9mjuYwkaJRQOXXaXN3yY3GQt0iUHFULBPlhX84LqcvYCo=
 =HSYo
 -----END PGP SIGNATURE-----

Merge tag 'memory-controller-drv-6.2-2' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl into soc/drivers

Memory controller drivers for v6.2, part two

1. ARM PL353: document PL354 in bindings.
2. TI/OMAP GPMC: allow setting wait-pin polarity.

* tag 'memory-controller-drv-6.2-2' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl:
  memory: omap-gpmc: fix coverity issue "Control flow issues"
  dt-bindings: memory-controllers: ti,gpmc: add wait-pin polarity
  memory: omap-gpmc: wait pin additions
  MAINTAINERS: arm,pl353-smc: correct dt-binding path
  dt-bindings: memory-controllers: arm,pl353-smc: Extend to support 'arm,pl354' SMC

Link: https://lore.kernel.org/r/20221116093509.19657-1-krzysztof.kozlowski@linaro.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2022-11-21 16:52:35 +01:00
commit fe04716e17
5 changed files with 178 additions and 41 deletions

View File

@ -1,26 +1,31 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/memory-controllers/arm,pl353-smc.yaml#
$id: http://devicetree.org/schemas/memory-controllers/arm,pl35x-smc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM PL353 Static Memory Controller (SMC) device-tree bindings
title: Arm PL35x Series Static Memory Controller (SMC)
maintainers:
- Miquel Raynal <miquel.raynal@bootlin.com>
- Naga Sureshkumar Relli <naga.sureshkumar.relli@xilinx.com>
description:
The PL353 Static Memory Controller is a bus where you can connect two kinds
description: |
The PL35x Static Memory Controller is a bus where you can connect two kinds
of memory interfaces, which are NAND and memory mapped interfaces (such as
SRAM or NOR).
SRAM or NOR) depending on the specific configuration.
The TRM is available here:
https://documentation-service.arm.com/static/5e8e2524fd977155116a58aa
# We need a select here so we don't match all nodes with 'arm,primecell'
select:
properties:
compatible:
contains:
const: arm,pl353-smc-r2p1
enum:
- arm,pl353-smc-r2p1
- arm,pl354
required:
- compatible
@ -30,7 +35,9 @@ properties:
compatible:
items:
- const: arm,pl353-smc-r2p1
- enum:
- arm,pl353-smc-r2p1
- arm,pl354
- const: arm,primecell
"#address-cells":
@ -46,30 +53,25 @@ properties:
The three chip select regions are defined in 'ranges'.
clocks:
items:
- description: clock for the memory device bus
- description: main clock of the SMC
minItems: 1
maxItems: 2
clock-names:
items:
- const: memclk
- const: apb_pclk
minItems: 1
maxItems: 2
ranges:
minItems: 1
description: |
Memory bus areas for interacting with the devices. Reflects
the memory layout with four integer values following:
<cs-number> 0 <offset> <size>
items:
- description: NAND bank 0
- description: NOR/SRAM bank 0
- description: NOR/SRAM bank 1
maxItems: 8
interrupts: true
interrupts:
minItems: 1
items:
- description: Combined or Memory interface 0 IRQ
- description: Memory interface 1 IRQ
patternProperties:
"@[0-3],[a-f0-9]+$":
"@[0-7],[a-f0-9]+$":
type: object
description: |
The child device node represents the controller connected to the SMC
@ -87,7 +89,7 @@ patternProperties:
- description: |
Chip-select ID, as in the parent range property.
minimum: 0
maximum: 2
maximum: 7
- description: |
Offset of the memory region requested by the device.
- description: |
@ -102,12 +104,36 @@ required:
- reg
- clock-names
- clocks
- "#address-cells"
- "#size-cells"
- ranges
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
const: arm,pl354
then:
properties:
clocks:
# According to TRM, really should be 3 clocks
maxItems: 1
clock-names:
const: apb_pclk
else:
properties:
clocks:
items:
- description: clock for the memory device bus
- description: main clock of the SMC
clock-names:
items:
- const: memclk
- const: apb_pclk
examples:
- |
smcc: memory-controller@e000e000 {

View File

@ -230,6 +230,13 @@ properties:
Wait-pin used by client. Must be less than "gpmc,num-waitpins".
$ref: /schemas/types.yaml#/definitions/uint32
ti,wait-pin-polarity:
description: |
Set the desired polarity for the selected wait pin.
0 for active low, 1 for active high.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1]
gpmc,wait-on-read:
description: Enables wait monitoring on reads.
type: boolean

View File

@ -1685,7 +1685,7 @@ M: Miquel Raynal <miquel.raynal@bootlin.com>
M: Naga Sureshkumar Relli <nagasure@xilinx.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/memory-controllers/arm,pl353-smc.yaml
F: Documentation/devicetree/bindings/memory-controllers/arm,pl35x-smc.yaml
F: drivers/memory/pl353-smc.c
ARM PRIMECELL CLCD PL110 DRIVER

View File

@ -134,6 +134,7 @@
#define GPMC_CONFIG_DEV_SIZE 0x00000002
#define GPMC_CONFIG_DEV_TYPE 0x00000003
#define GPMC_CONFIG_WAITPINPOLARITY(pin) (BIT(pin) << 8)
#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
#define GPMC_CONFIG1_READTYPE_ASYNC (0 << 29)
@ -229,6 +230,12 @@ struct omap3_gpmc_regs {
struct gpmc_cs_config cs_context[GPMC_CS_NUM];
};
struct gpmc_waitpin {
u32 pin;
u32 polarity;
struct gpio_desc *desc;
};
struct gpmc_device {
struct device *dev;
int irq;
@ -236,6 +243,7 @@ struct gpmc_device {
struct gpio_chip gpio_chip;
struct notifier_block nb;
struct omap3_gpmc_regs context;
struct gpmc_waitpin *waitpins;
int nirqs;
unsigned int is_suspended:1;
struct resource *data;
@ -1035,6 +1043,62 @@ void gpmc_cs_free(int cs)
}
EXPORT_SYMBOL(gpmc_cs_free);
static bool gpmc_is_valid_waitpin(u32 waitpin)
{
return waitpin < gpmc_nr_waitpins;
}
static int gpmc_alloc_waitpin(struct gpmc_device *gpmc,
struct gpmc_settings *p)
{
int ret;
struct gpmc_waitpin *waitpin;
struct gpio_desc *waitpin_desc;
if (!gpmc_is_valid_waitpin(p->wait_pin))
return -EINVAL;
waitpin = &gpmc->waitpins[p->wait_pin];
if (!waitpin->desc) {
/* Reserve the GPIO for wait pin usage.
* GPIO polarity doesn't matter here. Wait pin polarity
* is set in GPMC_CONFIG register.
*/
waitpin_desc = gpiochip_request_own_desc(&gpmc->gpio_chip,
p->wait_pin, "WAITPIN",
GPIO_ACTIVE_HIGH,
GPIOD_IN);
ret = PTR_ERR(waitpin_desc);
if (IS_ERR(waitpin_desc) && ret != -EBUSY)
return ret;
/* New wait pin */
waitpin->desc = waitpin_desc;
waitpin->pin = p->wait_pin;
waitpin->polarity = p->wait_pin_polarity;
} else {
/* Shared wait pin */
if (p->wait_pin_polarity != waitpin->polarity ||
p->wait_pin != waitpin->pin) {
dev_err(gpmc->dev,
"shared-wait-pin: invalid configuration\n");
return -EINVAL;
}
dev_info(gpmc->dev, "shared wait-pin: %d\n", waitpin->pin);
}
return 0;
}
static void gpmc_free_waitpin(struct gpmc_device *gpmc,
int wait_pin)
{
if (gpmc_is_valid_waitpin(wait_pin))
gpiochip_free_own_desc(gpmc->waitpins[wait_pin].desc);
}
/**
* gpmc_configure - write request to configure gpmc
* @cmd: command type
@ -1886,6 +1950,17 @@ int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, config1);
if (p->wait_pin_polarity != GPMC_WAITPINPOLARITY_INVALID) {
config1 = gpmc_read_reg(GPMC_CONFIG);
if (p->wait_pin_polarity == GPMC_WAITPINPOLARITY_ACTIVE_LOW)
config1 &= ~GPMC_CONFIG_WAITPINPOLARITY(p->wait_pin);
else if (p->wait_pin_polarity == GPMC_WAITPINPOLARITY_ACTIVE_HIGH)
config1 |= GPMC_CONFIG_WAITPINPOLARITY(p->wait_pin);
gpmc_write_reg(GPMC_CONFIG, config1);
}
return 0;
}
@ -1975,7 +2050,25 @@ void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
__func__);
}
p->wait_pin = GPMC_WAITPIN_INVALID;
p->wait_pin_polarity = GPMC_WAITPINPOLARITY_INVALID;
if (!of_property_read_u32(np, "gpmc,wait-pin", &p->wait_pin)) {
if (!gpmc_is_valid_waitpin(p->wait_pin)) {
pr_err("%s: Invalid wait-pin (%d)\n", __func__, p->wait_pin);
p->wait_pin = GPMC_WAITPIN_INVALID;
}
if (!of_property_read_u32(np, "ti,wait-pin-polarity",
&p->wait_pin_polarity)) {
if (p->wait_pin_polarity != GPMC_WAITPINPOLARITY_ACTIVE_HIGH &&
p->wait_pin_polarity != GPMC_WAITPINPOLARITY_ACTIVE_LOW) {
pr_err("%s: Invalid wait-pin-polarity (%d)\n",
__func__, p->wait_pin_polarity);
p->wait_pin_polarity = GPMC_WAITPINPOLARITY_INVALID;
}
}
p->wait_on_read = of_property_read_bool(np,
"gpmc,wait-on-read");
p->wait_on_write = of_property_read_bool(np,
@ -2080,7 +2173,6 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
const char *name;
int ret, cs;
u32 val;
struct gpio_desc *waitpin_desc = NULL;
struct gpmc_device *gpmc = platform_get_drvdata(pdev);
if (of_property_read_u32(child, "reg", &cs) < 0) {
@ -2208,17 +2300,9 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
/* Reserve wait pin if it is required and valid */
if (gpmc_s.wait_on_read || gpmc_s.wait_on_write) {
unsigned int wait_pin = gpmc_s.wait_pin;
waitpin_desc = gpiochip_request_own_desc(&gpmc->gpio_chip,
wait_pin, "WAITPIN",
GPIO_ACTIVE_HIGH,
GPIOD_IN);
if (IS_ERR(waitpin_desc)) {
dev_err(&pdev->dev, "invalid wait-pin: %d\n", wait_pin);
ret = PTR_ERR(waitpin_desc);
ret = gpmc_alloc_waitpin(gpmc, &gpmc_s);
if (ret < 0)
goto err;
}
}
gpmc_cs_show_timings(cs, "before gpmc_cs_program_settings");
@ -2260,7 +2344,7 @@ err_child_fail:
ret = -ENODEV;
err_cs:
gpiochip_free_own_desc(waitpin_desc);
gpmc_free_waitpin(gpmc, gpmc_s.wait_pin);
err:
gpmc_cs_free(cs);
@ -2489,7 +2573,7 @@ static int omap_gpmc_context_notifier(struct notifier_block *nb,
static int gpmc_probe(struct platform_device *pdev)
{
int rc;
int rc, i;
u32 l;
struct resource *res;
struct gpmc_device *gpmc;
@ -2545,6 +2629,15 @@ static int gpmc_probe(struct platform_device *pdev)
gpmc_nr_waitpins = GPMC_NR_WAITPINS;
}
gpmc->waitpins = devm_kzalloc(&pdev->dev,
gpmc_nr_waitpins * sizeof(struct gpmc_waitpin),
GFP_KERNEL);
if (!gpmc->waitpins)
return -ENOMEM;
for (i = 0; i < gpmc_nr_waitpins; i++)
gpmc->waitpins[i].pin = GPMC_WAITPIN_INVALID;
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
@ -2598,9 +2691,12 @@ gpio_init_failed:
static int gpmc_remove(struct platform_device *pdev)
{
int i;
struct gpmc_device *gpmc = platform_get_drvdata(pdev);
cpu_pm_unregister_notifier(&gpmc->nb);
for (i = 0; i < gpmc_nr_waitpins; i++)
gpmc_free_waitpin(gpmc, i);
gpmc_free_irq(gpmc);
gpmc_mem_exit();
pm_runtime_put_sync(&pdev->dev);

View File

@ -136,6 +136,13 @@ struct gpmc_device_timings {
#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */
#define GPMC_MUX_AD 2 /* Addr-Data multiplex */
/* Wait pin polarity values */
#define GPMC_WAITPINPOLARITY_INVALID UINT_MAX
#define GPMC_WAITPINPOLARITY_ACTIVE_LOW 0
#define GPMC_WAITPINPOLARITY_ACTIVE_HIGH 1
#define GPMC_WAITPIN_INVALID UINT_MAX
struct gpmc_settings {
bool burst_wrap; /* enables wrap bursting */
bool burst_read; /* enables read page/burst mode */
@ -149,6 +156,7 @@ struct gpmc_settings {
u32 device_width; /* device bus width (8 or 16 bit) */
u32 mux_add_data; /* multiplex address & data */
u32 wait_pin; /* wait-pin to be used */
u32 wait_pin_polarity;
};
/* Data for each chip select */