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:
commit
fe04716e17
@ -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 {
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,18 +2300,10 @@ 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);
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user