Commit 2e368dd2 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc

Pull ARM SoC-related driver updates from Olof Johansson:
 "Various driver updates for platforms. A bulk of this is smaller fixes
  or cleanups, but some of the new material this time around is:

   - Support for Nvidia Tegra234 SoC

   - Ring accelerator support for TI AM65x

   - PRUSS driver for TI platforms

   - Renesas support for R-Car V3U SoC

   - Reset support for Cortex-M4 processor on i.MX8MQ

  There are also new socinfo entries for a handful of different SoCs and
  platforms"

* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (131 commits)
  drm/mediatek: reduce clear event
  soc: mediatek: cmdq: add clear option in cmdq_pkt_wfe api
  soc: mediatek: cmdq: add jump function
  soc: mediatek: cmdq: add write_s_mask value function
  soc: mediatek: cmdq: add write_s value function
  soc: mediatek: cmdq: add read_s function
  soc: mediatek: cmdq: add write_s_mask function
  soc: mediatek: cmdq: add write_s function
  soc: mediatek: cmdq: add address shift in jump
  soc: mediatek: mtk-infracfg: Fix kerneldoc
  soc: amlogic: pm-domains: use always-on flag
  reset: sti: reset-syscfg: fix struct description warnings
  reset: imx7: add the cm4 reset for i.MX8MQ
  dt-bindings: reset: imx8mq: add m4 reset
  reset: Fix and extend kerneldoc
  reset: reset-zynqmp: Added support for Versal platform
  dt-bindings: reset: Updated binding for Versal reset driver
  reset: imx7: Support module build
  soc: fsl: qe: Remove unnessesary check in ucc_set_tdm_rxtx_clk
  soc: fsl: qman: convert to use be32_add_cpu()
  ...
parents e731f314 9f7f2693
......@@ -10,7 +10,8 @@ Required properties:
"brcm,bcm7038-gisb-arb" for 130nm chips
- reg: specifies the base physical address and size of the registers
- interrupts: specifies the two interrupts (timeout and TEA) to be used from
the parent interrupt controller
the parent interrupt controller. A third optional interrupt may be specified
for breakpoints.
Optional properties:
......
......@@ -5,7 +5,7 @@ The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
Mediatek SMI have two generations of HW architecture, here is the list
which generation the SoCs use:
generation 1: mt2701 and mt7623.
generation 2: mt2712, mt6779, mt8173 and mt8183.
generation 2: mt2712, mt6779, mt8167, mt8173 and mt8183.
There's slight differences between the two SMI, for generation 2, the
register which control the iommu port is at each larb's register base. But
......@@ -20,6 +20,7 @@ Required properties:
"mediatek,mt2712-smi-common"
"mediatek,mt6779-smi-common"
"mediatek,mt7623-smi-common", "mediatek,mt2701-smi-common"
"mediatek,mt8167-smi-common"
"mediatek,mt8173-smi-common"
"mediatek,mt8183-smi-common"
- reg : the register and size of the SMI block.
......
......@@ -8,6 +8,7 @@ Required properties:
"mediatek,mt2712-smi-larb"
"mediatek,mt6779-smi-larb"
"mediatek,mt7623-smi-larb", "mediatek,mt2701-smi-larb"
"mediatek,mt8167-smi-larb"
"mediatek,mt8173-smi-larb"
"mediatek,mt8183-smi-larb"
- reg : the register and size of this local arbiter.
......@@ -22,7 +23,7 @@ Required properties:
- "gals": the clock for GALS(Global Async Local Sync).
Here is the list which has this GALS: mt8183.
Required property for mt2701, mt2712, mt6779 and mt7623:
Required property for mt2701, mt2712, mt6779, mt7623 and mt8167:
- mediatek,larb-id :the hardware id of this larb.
Example:
......
......@@ -27,6 +27,7 @@ properties:
- amlogic,meson8b-pwrc
- amlogic,meson8m2-pwrc
- amlogic,meson-gxbb-pwrc
- amlogic,meson-axg-pwrc
- amlogic,meson-g12a-pwrc
- amlogic,meson-sm1-pwrc
......@@ -42,11 +43,11 @@ properties:
- const: vapb
resets:
minItems: 11
minItems: 5
maxItems: 12
reset-names:
minItems: 11
minItems: 5
maxItems: 12
"#power-domain-cells":
......@@ -107,6 +108,24 @@ allOf:
- resets
- reset-names
- if:
properties:
compatible:
enum:
- amlogic,meson-axg-pwrc
then:
properties:
reset-names:
items:
- const: viu
- const: venc
- const: vcbus
- const: vencl
- const: vid_lock
required:
- resets
- reset-names
- if:
properties:
compatible:
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/power/brcm,bcm63xx-power.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: BCM63xx power domain driver
maintainers:
- Álvaro Fernández Rojas <noltari@gmail.com>
description: |
BCM6318, BCM6328, BCM6362 and BCM63268 SoCs have a power domain controller
to enable/disable certain components in order to save power.
properties:
compatible:
items:
- enum:
- brcm,bcm6318-power-controller
- brcm,bcm6328-power-controller
- brcm,bcm6362-power-controller
- brcm,bcm63268-power-controller
reg:
maxItems: 1
"#power-domain-cells":
const: 1
required:
- compatible
- reg
- "#power-domain-cells"
additionalProperties: false
examples:
- |
periph_pwr: power-controller@10001848 {
compatible = "brcm,bcm6328-power-controller";
reg = <0x10001848 0x4>;
#power-domain-cells = <1>;
};
--------------------------------------------------------------------------
= Zynq UltraScale+ MPSoC reset driver binding =
= Zynq UltraScale+ MPSoC and Versal reset driver binding =
--------------------------------------------------------------------------
The Zynq UltraScale+ MPSoC has several different resets.
The Zynq UltraScale+ MPSoC and Versal has several different resets.
See Chapter 36 of the Zynq UltraScale+ MPSoC TRM (UG) for more information
about zynqmp resets.
......@@ -10,7 +10,8 @@ Please also refer to reset.txt in this directory for common reset
controller binding usage.
Required Properties:
- compatible: "xlnx,zynqmp-reset"
- compatible: "xlnx,zynqmp-reset" for Zynq UltraScale+ MPSoC platform
"xlnx,versal-reset" for Versal platform
- #reset-cells: Specifies the number of cells needed to encode reset
line, should be 1
......@@ -37,8 +38,10 @@ Device nodes that need access to reset lines should
specify them as a reset phandle in their corresponding node as
specified in reset.txt.
For list of all valid reset indicies see
For list of all valid reset indices for Zynq UltraScale+ MPSoC see
<dt-bindings/reset/xlnx-zynqmp-resets.h>
For list of all valid reset indices for Versal see
<dt-bindings/reset/xlnx-versal-resets.h>
Example:
......
......@@ -62,11 +62,6 @@ properties:
$ref: /schemas/types.yaml#/definitions/uint32
description: TI-SCI device id of the ring accelerator
ti,dma-ring-reset-quirk:
$ref: /schemas/types.yaml#definitions/flag
description: |
enable ringacc/udma ring state interoperability issue software w/a
required:
- compatible
- reg
......@@ -94,7 +89,6 @@ examples:
reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target";
ti,num-rings = <818>;
ti,sci-rm-range-gp-rings = <0x2>; /* GP ring range */
ti,dma-ring-reset-quirk;
ti,sci = <&dmsc>;
ti,sci-dev-id = <187>;
msi-parent = <&inta_main_udmass>;
......
This diff is collapsed.
......@@ -3482,6 +3482,7 @@ F: arch/mips/bmips/*
F: arch/mips/boot/dts/brcm/bcm*.dts*
F: arch/mips/include/asm/mach-bmips/*
F: arch/mips/kernel/*bmips*
F: drivers/soc/bcm/bcm63xx
F: drivers/irqchip/irq-bcm63*
F: drivers/irqchip/irq-bcm7*
F: drivers/irqchip/irq-brcmstb*
......
......@@ -117,6 +117,12 @@ leds0: led-controller@10001900 {
status = "disabled";
};
periph_pwr: power-controller@1000184c {
compatible = "brcm,bcm6328-power-controller";
reg = <0x1000184c 0x4>;
#power-domain-cells = <1>;
};
ehci: usb@10002500 {
compatible = "brcm,bcm63268-ehci", "generic-ehci";
reg = <0x10002500 0x100>;
......
......@@ -110,6 +110,12 @@ leds0: led-controller@10000800 {
status = "disabled";
};
periph_pwr: power-controller@10001848 {
compatible = "brcm,bcm6328-power-controller";
reg = <0x10001848 0x4>;
#power-domain-cells = <1>;
};
ehci: usb@10002500 {
compatible = "brcm,bcm6328-ehci", "generic-ehci";
reg = <0x10002500 0x100>;
......
......@@ -108,6 +108,12 @@ uart1: serial@10000120 {
status = "disabled";
};
periph_pwr: power-controller@10001848 {
compatible = "brcm,bcm6362-power-controller";
reg = <0x10001848 0x4>;
#power-domain-cells = <1>;
};
leds0: led-controller@10001900 {
#address-cells = <1>;
#size-cells = <0>;
......
......@@ -30,8 +30,22 @@
#define ARB_ERR_CAP_STATUS_WRITE (1 << 1)
#define ARB_ERR_CAP_STATUS_VALID (1 << 0)
#define ARB_BP_CAP_CLEAR (1 << 0)
#define ARB_BP_CAP_STATUS_PROT_SHIFT 14
#define ARB_BP_CAP_STATUS_TYPE (1 << 13)
#define ARB_BP_CAP_STATUS_RSP_SHIFT 10
#define ARB_BP_CAP_STATUS_MASK GENMASK(1, 0)
#define ARB_BP_CAP_STATUS_BS_SHIFT 2
#define ARB_BP_CAP_STATUS_WRITE (1 << 1)
#define ARB_BP_CAP_STATUS_VALID (1 << 0)
enum {
ARB_TIMER,
ARB_BP_CAP_CLR,
ARB_BP_CAP_HI_ADDR,
ARB_BP_CAP_ADDR,
ARB_BP_CAP_STATUS,
ARB_BP_CAP_MASTER,
ARB_ERR_CAP_CLR,
ARB_ERR_CAP_HI_ADDR,
ARB_ERR_CAP_ADDR,
......@@ -41,6 +55,11 @@ enum {
static const int gisb_offsets_bcm7038[] = {
[ARB_TIMER] = 0x00c,
[ARB_BP_CAP_CLR] = 0x014,
[ARB_BP_CAP_HI_ADDR] = -1,
[ARB_BP_CAP_ADDR] = 0x0b8,
[ARB_BP_CAP_STATUS] = 0x0c0,
[ARB_BP_CAP_MASTER] = -1,
[ARB_ERR_CAP_CLR] = 0x0c4,
[ARB_ERR_CAP_HI_ADDR] = -1,
[ARB_ERR_CAP_ADDR] = 0x0c8,
......@@ -50,6 +69,11 @@ static const int gisb_offsets_bcm7038[] = {
static const int gisb_offsets_bcm7278[] = {
[ARB_TIMER] = 0x008,
[ARB_BP_CAP_CLR] = 0x01c,
[ARB_BP_CAP_HI_ADDR] = -1,
[ARB_BP_CAP_ADDR] = 0x220,
[ARB_BP_CAP_STATUS] = 0x230,
[ARB_BP_CAP_MASTER] = 0x234,
[ARB_ERR_CAP_CLR] = 0x7f8,
[ARB_ERR_CAP_HI_ADDR] = -1,
[ARB_ERR_CAP_ADDR] = 0x7e0,
......@@ -59,6 +83,11 @@ static const int gisb_offsets_bcm7278[] = {
static const int gisb_offsets_bcm7400[] = {
[ARB_TIMER] = 0x00c,
[ARB_BP_CAP_CLR] = 0x014,
[ARB_BP_CAP_HI_ADDR] = -1,
[ARB_BP_CAP_ADDR] = 0x0b8,
[ARB_BP_CAP_STATUS] = 0x0c0,
[ARB_BP_CAP_MASTER] = 0x0c4,
[ARB_ERR_CAP_CLR] = 0x0c8,
[ARB_ERR_CAP_HI_ADDR] = -1,
[ARB_ERR_CAP_ADDR] = 0x0cc,
......@@ -68,6 +97,11 @@ static const int gisb_offsets_bcm7400[] = {
static const int gisb_offsets_bcm7435[] = {
[ARB_TIMER] = 0x00c,
[ARB_BP_CAP_CLR] = 0x014,
[ARB_BP_CAP_HI_ADDR] = -1,
[ARB_BP_CAP_ADDR] = 0x158,
[ARB_BP_CAP_STATUS] = 0x160,
[ARB_BP_CAP_MASTER] = 0x164,
[ARB_ERR_CAP_CLR] = 0x168,
[ARB_ERR_CAP_HI_ADDR] = -1,
[ARB_ERR_CAP_ADDR] = 0x16c,
......@@ -77,6 +111,11 @@ static const int gisb_offsets_bcm7435[] = {
static const int gisb_offsets_bcm7445[] = {
[ARB_TIMER] = 0x008,
[ARB_BP_CAP_CLR] = 0x010,
[ARB_BP_CAP_HI_ADDR] = -1,
[ARB_BP_CAP_ADDR] = 0x1d8,
[ARB_BP_CAP_STATUS] = 0x1e0,
[ARB_BP_CAP_MASTER] = 0x1e4,
[ARB_ERR_CAP_CLR] = 0x7e4,
[ARB_ERR_CAP_HI_ADDR] = 0x7e8,
[ARB_ERR_CAP_ADDR] = 0x7ec,
......@@ -125,6 +164,16 @@ static u64 gisb_read_address(struct brcmstb_gisb_arb_device *gdev)
return value;
}
static u64 gisb_read_bp_address(struct brcmstb_gisb_arb_device *gdev)
{
u64 value;
value = gisb_read(gdev, ARB_BP_CAP_ADDR);
value |= (u64)gisb_read(gdev, ARB_BP_CAP_HI_ADDR) << 32;
return value;
}
static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg)
{
int offset = gdev->gisb_offsets[reg];
......@@ -210,8 +259,8 @@ static int brcmstb_gisb_arb_decode_addr(struct brcmstb_gisb_arb_device *gdev,
m_name = m_fmt;
}
pr_crit("%s: %s at 0x%llx [%c %s], core: %s\n",
__func__, reason, arb_addr,
pr_crit("GISB: %s at 0x%llx [%c %s], core: %s\n",
reason, arb_addr,
cap_status & ARB_ERR_CAP_STATUS_WRITE ? 'W' : 'R',
cap_status & ARB_ERR_CAP_STATUS_TIMEOUT ? "timeout" : "",
m_name);
......@@ -259,6 +308,41 @@ static irqreturn_t brcmstb_gisb_tea_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
static irqreturn_t brcmstb_gisb_bp_handler(int irq, void *dev_id)
{
struct brcmstb_gisb_arb_device *gdev = dev_id;
const char *m_name;
u32 bp_status;
u64 arb_addr;
u32 master;
char m_fmt[11];
bp_status = gisb_read(gdev, ARB_BP_CAP_STATUS);
/* Invalid captured address, bail out */
if (!(bp_status & ARB_BP_CAP_STATUS_VALID))
return IRQ_HANDLED;
/* Read the address and master */
arb_addr = gisb_read_bp_address(gdev);
master = gisb_read(gdev, ARB_BP_CAP_MASTER);
m_name = brcmstb_gisb_master_to_str(gdev, master);
if (!m_name) {
snprintf(m_fmt, sizeof(m_fmt), "0x%08x", master);
m_name = m_fmt;
}
pr_crit("GISB: breakpoint at 0x%llx [%c], core: %s\n",
arb_addr, bp_status & ARB_BP_CAP_STATUS_WRITE ? 'W' : 'R',
m_name);
/* clear the GISB error */
gisb_write(gdev, ARB_ERR_CAP_CLEAR, ARB_ERR_CAP_CLR);
return IRQ_HANDLED;
}
/*
* Dump out gisb errors on die or panic.
*/
......@@ -317,13 +401,14 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
struct brcmstb_gisb_arb_device *gdev;
const struct of_device_id *of_id;
struct resource *r;
int err, timeout_irq, tea_irq;
int err, timeout_irq, tea_irq, bp_irq;
unsigned int num_masters, j = 0;
int i, first, last;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
timeout_irq = platform_get_irq(pdev, 0);
tea_irq = platform_get_irq(pdev, 1);
bp_irq = platform_get_irq(pdev, 2);
gdev = devm_kzalloc(&pdev->dev, sizeof(*gdev), GFP_KERNEL);
if (!gdev)
......@@ -356,6 +441,15 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
if (err < 0)
return err;
/* Interrupt is optional */
if (bp_irq > 0) {
err = devm_request_irq(&pdev->dev, bp_irq,
brcmstb_gisb_bp_handler, 0, pdev->name,
gdev);
if (err < 0)
return err;
}
/* If we do not have a valid mask, assume all masters are enabled */
if (of_property_read_u32(dn, "brcm,gisb-arb-master-mask",
&gdev->valid_mask))
......
......@@ -29,7 +29,7 @@ static const struct scmi_handle *handle;
static unsigned int scmi_cpufreq_get_rate(unsigned int cpu)
{
struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu);
struct scmi_perf_ops *perf_ops = handle->perf_ops;
const struct scmi_perf_ops *perf_ops = handle->perf_ops;
struct scmi_data *priv = policy->driver_data;
unsigned long rate;
int ret;
......@@ -49,7 +49,7 @@ static int
scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
{
struct scmi_data *priv = policy->driver_data;
struct scmi_perf_ops *perf_ops = handle->perf_ops;
const struct scmi_perf_ops *perf_ops = handle->perf_ops;
u64 freq = policy->freq_table[index].frequency;
return perf_ops->freq_set(handle, priv->domain_id, freq * 1000, false);
......@@ -59,7 +59,7 @@ static unsigned int scmi_cpufreq_fast_switch(struct cpufreq_policy *policy,
unsigned int target_freq)
{
struct scmi_data *priv = policy->driver_data;
struct scmi_perf_ops *perf_ops = handle->perf_ops;
const struct scmi_perf_ops *perf_ops = handle->perf_ops;
if (!perf_ops->freq_set(handle, priv->domain_id,
target_freq * 1000, true))
......
......@@ -573,8 +573,8 @@ static int k3_udma_glue_cfg_rx_flow(struct k3_udma_glue_rx_channel *rx_chn,
/* request and cfg rings */
ret = k3_ringacc_request_rings_pair(rx_chn->common.ringacc,
flow_cfg->ring_rxq_id,
flow_cfg->ring_rxfdq0_id,
flow_cfg->ring_rxq_id,
&flow->ringrxfdq,
&flow->ringrx);
if (ret) {
......
......@@ -7,7 +7,7 @@
menu "Firmware Drivers"
config ARM_SCMI_PROTOCOL
bool "ARM System Control and Management Interface (SCMI) Message Protocol"
tristate "ARM System Control and Management Interface (SCMI) Message Protocol"
depends on ARM || ARM64 || COMPILE_TEST
depends on MAILBOX
help
......
......@@ -22,7 +22,7 @@ obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o
obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/
obj-y += arm_scmi/
obj-y += broadcom/
obj-y += meson/
obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
......
# SPDX-License-Identifier: GPL-2.0-only
obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o scmi-transport.o
scmi-bus-y = bus.o
scmi-driver-y = driver.o notify.o
scmi-transport-y = shmem.o
scmi-transport-$(CONFIG_MAILBOX) += mailbox.o
scmi-transport-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smc.o
scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o
scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o
scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \
$(scmi-transport-y)
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o
obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
......@@ -230,7 +230,7 @@ static void scmi_devices_unregister(void)
bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister);
}
static int __init scmi_bus_init(void)
int __init scmi_bus_init(void)
{
int retval;
......@@ -240,12 +240,10 @@ static int __init scmi_bus_init(void)
return retval;
}
subsys_initcall(scmi_bus_init);
static void __exit scmi_bus_exit(void)
void __exit scmi_bus_exit(void)
{
scmi_devices_unregister();
bus_unregister(&scmi_bus_type);
ida_destroy(&scmi_bus_id);
}
module_exit(scmi_bus_exit);
......@@ -318,7 +318,7 @@ scmi_clock_info_get(const struct scmi_handle *handle, u32 clk_id)
return clk;
}
static struct scmi_clk_ops clk_ops = {
static const struct scmi_clk_ops clk_ops = {
.count_get = scmi_clock_count_get,
.info_get = scmi_clock_info_get,
.rate_get = scmi_clock_rate_get,
......@@ -364,9 +364,4 @@ static int scmi_clock_protocol_init(struct scmi_handle *handle)
return 0;
}
static int __init scmi_clock_init(void)
{
return scmi_protocol_register(SCMI_PROTOCOL_CLOCK,
&scmi_clock_protocol_init);
}
subsys_initcall(scmi_clock_init);
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_CLOCK, clock)
......@@ -156,6 +156,30 @@ void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
int scmi_base_protocol_init(struct scmi_handle *h);
int __init scmi_bus_init(void);
void __exit scmi_bus_exit(void);
#define DECLARE_SCMI_REGISTER_UNREGISTER(func) \
int __init scmi_##func##_register(void); \
void __exit scmi_##func##_unregister(void)
DECLARE_SCMI_REGISTER_UNREGISTER(clock);
DECLARE_SCMI_REGISTER_UNREGISTER(perf);
DECLARE_SCMI_REGISTER_UNREGISTER(power);
DECLARE_SCMI_REGISTER_UNREGISTER(reset);
DECLARE_SCMI_REGISTER_UNREGISTER(sensors);
DECLARE_SCMI_REGISTER_UNREGISTER(system);
#define DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(id, name) \
int __init scmi_##name##_register(void) \
{ \
return scmi_protocol_register((id), &scmi_##name##_protocol_init); \
} \
\
void __exit scmi_##name##_unregister(void) \
{ \
scmi_protocol_unregister((id)); \
}
/* SCMI Transport */
/**
* struct scmi_chan_info - Structure representing a SCMI channel information
......@@ -210,7 +234,7 @@ struct scmi_transport_ops {
* @max_msg_size: Maximum size of data per message that can be handled.
*/
struct scmi_desc {
struct scmi_transport_ops *ops;
const struct scmi_transport_ops *ops;
int max_rx_timeout_ms;
int max_msg;
int max_msg_size;
......
......@@ -730,6 +730,7 @@ struct scmi_prot_devnames {
static struct scmi_prot_devnames devnames[] = {
{ SCMI_PROTOCOL_POWER, { "genpd" },},
{ SCMI_PROTOCOL_SYSTEM, { "syspower" },},
{ SCMI_PROTOCOL_PERF, { "cpufreq" },},
{ SCMI_PROTOCOL_CLOCK, { "clocks" },},
{ SCMI_PROTOCOL_SENSOR, { "hwmon" },},
......@@ -928,7 +929,35 @@ static struct platform_driver scmi_driver = {
.remove = scmi_remove,
};
module_platform_driver(scmi_driver);
static int __init scmi_driver_init(void)
{
scmi_bus_init();
scmi_clock_register();
scmi_perf_register();
scmi_power_register();
scmi_reset_register();
scmi_sensors_register();
scmi_system_register();
return platform_driver_register(&scmi_driver);
}
subsys_initcall(scmi_driver_init);
static void __exit scmi_driver_exit(void)
{
scmi_bus_exit();
scmi_clock_unregister();
scmi_perf_unregister();
scmi_power_unregister();
scmi_reset_unregister();
scmi_sensors_unregister();
scmi_system_unregister();
platform_driver_unregister(&scmi_driver);
}
module_exit(scmi_driver_exit);
MODULE_ALIAS("platform: arm-scmi");
MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
......
......@@ -110,7 +110,7 @@ static int mailbox_chan_free(int id, void *p, void *data)
struct scmi_chan_info *cinfo = p;
struct scmi_mailbox *smbox = cinfo->transport_info;
if (!IS_ERR(smbox->chan)) {
if (smbox && !IS_ERR(smbox->chan)) {
mbox_free_channel(smbox->chan);
cinfo->transport_info = NULL;
smbox->chan = NULL;
......@@ -181,7 +181,7 @@ mailbox_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
return shmem_poll_done(smbox->shmem, xfer);
}
static struct scmi_transport_ops scmi_mailbox_ops = {
static const struct scmi_transport_ops scmi_mailbox_ops = {
.chan_available = mailbox_chan_available,
.chan_setup = mailbox_chan_setup,
.chan_free = mailbox_chan_free,
......
......@@ -1421,7 +1421,7 @@ static void scmi_protocols_late_init(struct work_struct *work)
* notify_ops are attached to the handle so that can be accessed
* directly from an scmi_driver to register its own notifiers.
*/
static struct scmi_notify_ops notify_ops = {
static const struct scmi_notify_ops notify_ops = {
.register_event_notifier = scmi_register_notifier,
.unregister_event_notifier = scmi_unregister_notifier,
};
......
......@@ -748,7 +748,7 @@ static bool scmi_fast_switch_possible(const struct scmi_handle *handle,
return dom->fc_info && dom->fc_info->level_set_addr;
}
static struct scmi_perf_ops perf_ops = {
static const struct scmi_perf_ops perf_ops = {
.limits_set = scmi_perf_limits_set,
.limits_get = scmi_perf_limits_get,
.level_set = scmi_perf_level_set,
......@@ -890,9 +890,4 @@ static int scmi_perf_protocol_init(struct scmi_handle *handle)
return 0;
}
static int __init scmi_perf_init(void)
{
return scmi_protocol_register(SCMI_PROTOCOL_PERF,
&scmi_perf_protocol_init);
}
subsys_initcall(scmi_perf_init);
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_PERF, perf)
......@@ -184,7 +184,7 @@ static char *scmi_power_name_get(const struct scmi_handle *handle, u32 domain)
return dom->name;
}
static struct scmi_power_ops power_ops = {
static const struct scmi_power_ops power_ops = {
.num_domains_get = scmi_power_num_domains_get,
.name_get = scmi_power_name_get,
.state_set = scmi_power_state_set,
......@@ -301,9 +301,4 @@ static int scmi_power_protocol_init(struct scmi_handle *handle)
return 0;
}
static int __init scmi_power_init(void)
{
return scmi_protocol_register(SCMI_PROTOCOL_POWER,
&scmi_power_protocol_init);
}
subsys_initcall(scmi_power_init);
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_POWER, power)
......@@ -194,7 +194,7 @@ scmi_reset_domain_deassert(const struct scmi_handle *handle, u32 domain)
return scmi_domain_reset(handle, domain, 0, ARCH_COLD_RESET);
}
static struct scmi_reset_ops reset_ops = {
static const struct scmi_reset_ops reset_ops = {
.num_domains_get = scmi_reset_num_domains_get,
.name_get = scmi_reset_name_get,
.latency_get = scmi_reset_latency_get,
......@@ -313,9 +313,4 @@ static int scmi_reset_protocol_init(struct scmi_handle *handle)
return 0;
}
static int __init scmi_reset_init(void)
{
return scmi_protocol_register(SCMI_PROTOCOL_RESET,
&scmi_reset_protocol_init);
}
subsys_initcall(scmi_reset_init);
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_RESET, reset)
......@@ -275,7 +275,7 @@ static int scmi_sensor_count_get(const struct scmi_handle *handle)
return si->num_sensors;
}
static struct scmi_sensor_ops sensor_ops = {
static const struct scmi_sensor_ops sensor_ops = {
.count_get = scmi_sensor_count_get,
.info_get = scmi_sensor_info_get,
.trip_point_config = scmi_sensor_trip_point_config,
......@@ -365,9 +365,4 @@ static int scmi_sensors_protocol_init(struct scmi_handle *handle)
return 0;
}
static int __init scmi_sensors_init(void)
{
return scmi_protocol_register(SCMI_PROTOCOL_SENSOR,
&scmi_sensors_protocol_init);
}
subsys_initcall(scmi_sensors_init);
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_SENSOR, sensors)
......@@ -137,7 +137,7 @@ smc_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
return shmem_poll_done(scmi_info->shmem, xfer);
}
static struct scmi_transport_ops scmi_smc_ops = {
static const struct scmi_transport_ops scmi_smc_ops = {
.chan_available = smc_chan_available,
.chan_setup = smc_chan_setup,
.chan_free = smc_chan_free,
......
// SPDX-License-Identifier: GPL-2.0
/*
* System Control and Management Interface (SCMI) System Power Protocol
*
* Copyright (C) 2020 ARM Ltd.
*/
#define pr_fmt(fmt) "SCMI Notifications SYSTEM - " fmt
#include <linux/scmi_protocol.h>
#include "common.h"
#include "notify.h"
#define SCMI_SYSTEM_NUM_SOURCES 1
enum scmi_system_protocol_cmd {
SYSTEM_POWER_STATE_NOTIFY = 0x5,
};
struct scmi_system_power_state_notify {
__le32 notify_enable;
};
struct scmi_system_power_state_notifier_payld {
__le32 agent_id;
__le32 flags;
__le32 system_state;
};
struct scmi_system_info {
u32 version;
};
static int scmi_system_request_notify(const struct scmi_handle *handle,
bool enable)
{
int ret;
struct scmi_xfer *t;
struct scmi_system_power_state_notify *notify;
ret = scmi_xfer_get_init(handle, SYSTEM_POWER_STATE_NOTIFY,
SCMI_PROTOCOL_SYSTEM, sizeof(*notify), 0, &t);
if (ret)
return ret;
notify = t->tx.buf;
notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0;
ret = scmi_do_xfer(handle, t);
scmi_xfer_put(handle, t);
return ret;
}
static int scmi_system_set_notify_enabled(const struct scmi_handle *handle,
u8 evt_id, u32 src_id, bool enable)
{
int ret;
ret = scmi_system_request_notify(handle, enable);
if (ret)
pr_debug("FAIL_ENABLE - evt[%X] - ret:%d\n", evt_id, ret);
return ret;
}
static void *scmi_system_fill_custom_report(const struct scmi_handle *handle,
u8 evt_id, ktime_t timestamp,
const void *payld, size_t payld_sz,
void *report, u32 *src_id)
{
const struct scmi_system_power_state_notifier_payld *p = payld;
struct scmi_system_power_state_notifier_report *r = report;
if (evt_id != SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER ||
sizeof(*p) != payld_sz)
return NULL;
r->timestamp = timestamp;
r->agent_id = le32_to_cpu(p->agent_id);
r->flags = le32_to_cpu(p->flags);
r->system_state = le32_to_cpu(p->system_state);
*src_id = 0;
return r;
}
static const struct scmi_event system_events[] = {
{
.id = SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER,
.max_payld_sz =
sizeof(struct scmi_system_power_state_notifier_payld),
.max_report_sz =
sizeof(struct scmi_system_power_state_notifier_report),
},
};
static const struct scmi_event_ops system_event_ops = {
.set_notify_enabled = scmi_system_set_notify_enabled,
.fill_custom_report = scmi_system_fill_custom_report,
};
static int scmi_system_protocol_init(struct scmi_handle *handle)
{
u32 version;
struct scmi_system_info *pinfo;
scmi_version_get(handle, SCMI_PROTOCOL_SYSTEM, &version);
dev_dbg(handle->dev, "System Power Version %d.%d\n",
PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
pinfo = devm_kzalloc(handle->dev, sizeof(*pinfo), GFP_KERNEL);
if (!pinfo)
return -ENOMEM;
scmi_register_protocol_events(handle,
SCMI_PROTOCOL_SYSTEM, SCMI_PROTO_QUEUE_SZ,
&system_event_ops,
system_events,
ARRAY_SIZE(system_events),
SCMI_SYSTEM_NUM_SOURCES);
pinfo->version = version;
handle->system_priv = pinfo;
return 0;
}
DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_SYSTEM, system)
......@@ -46,6 +46,7 @@
#include <dt-bindings/firmware/imx/rsrc.h>
#include <linux/firmware/imx/sci.h>
#include <linux/firmware/imx/svc/rm.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
......@@ -256,6 +257,9 @@ imx_scu_add_pm_domain(struct device *dev, int idx,
struct imx_sc_pm_domain *sc_pd;
int ret;
if (!imx_sc_rm_is_resource_owned(pm_ipc_handle, pd_ranges->rsrc + idx))
return NULL;
sc_pd = devm_kzalloc(dev, sizeof(*sc_pd), GFP_KERNEL);
if (!sc_pd)
return ERR_PTR(-ENOMEM);
......
......@@ -24,8 +24,10 @@ enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void)
return smccc_conduit;
}
EXPORT_SYMBOL_GPL(arm_smccc_1_1_get_conduit);
u32 arm_smccc_get_version(void)
{
return smccc_version;
}
EXPORT_SYMBOL_GPL(arm_smccc_get_version);
......@@ -856,7 +856,8 @@ static const struct tegra_bpmp_soc tegra210_soc = {
static const struct of_device_id tegra_bpmp_match[] = {
#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \
IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
{ .compatible = "nvidia,tegra186-bpmp", .data = &tegra186_soc },
#endif
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
......
......@@ -1106,7 +1106,8 @@ static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id,
static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
u32 dev_id, u32 clk_id)
{
return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
return ti_sci_set_clock_state(handle, dev_id, clk_id,
MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE,
MSG_CLOCK_SW_STATE_UNREQ);
}
......@@ -1125,7 +1126,8 @@ static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle,
u32 dev_id, u32 clk_id)
{
return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
return ti_sci_set_clock_state(handle, dev_id, clk_id,
MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE,
MSG_CLOCK_SW_STATE_AUTO);
}
......
......@@ -481,7 +481,7 @@ static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_crtc)
mbox_flush(mtk_crtc->cmdq_client->chan, 2000);
cmdq_handle = cmdq_pkt_create(mtk_crtc->cmdq_client, PAGE_SIZE);
cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event);
cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event);
cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false);
mtk_crtc_ddp_config(crtc, cmdq_handle);
cmdq_pkt_finalize(cmdq_handle);
cmdq_pkt_flush_async(cmdq_handle, ddp_cmdq_cb, cmdq_handle);
......
......@@ -13,6 +13,8 @@
#include <linux/pm.h>
#include <linux/slab.h>
#include <soc/tegra/fuse.h>
#include <dt-bindings/mailbox/tegra186-hsp.h>
#include "mailbox.h"
......@@ -322,7 +324,12 @@ static int tegra_hsp_doorbell_startup(struct mbox_chan *chan)
if (!ccplex)
return -ENODEV;
if (!tegra_hsp_doorbell_can_ring(db))
/*
* On simulation platforms the BPMP hasn't had a chance yet to mark
* the doorbell as ringable by the CCPLEX, so we want to skip extra
* checks here.
*/
if (tegra_is_silicon() && !tegra_hsp_doorbell_can_ring(db))
return -ENODEV;
spin_lock_irqsave(&hsp->lock, flags);
......
......@@ -32,8 +32,9 @@ config ARM_PL172_MPMC
config ATMEL_SDRAMC
bool "Atmel (Multi-port DDR-)SDRAM Controller"
default y
depends on ARCH_AT91 && OF
default y if ARCH_AT91
depends on ARCH_AT91 || COMPILE_TEST
depends on OF
help
This driver is for Atmel SDRAM Controller or Atmel Multi-port
DDR-SDRAM Controller available on Atmel AT91SAM9 and SAMA5 SoCs.
......@@ -42,8 +43,9 @@ config ATMEL_SDRAMC
config ATMEL_EBI
bool "Atmel EBI driver"
default y
depends on ARCH_AT91 && OF
default y if ARCH_AT91
depends on ARCH_AT91 || COMPILE_TEST
depends on OF
select MFD_SYSCON
select MFD_ATMEL_SMC
help
......@@ -52,6 +54,18 @@ config ATMEL_EBI
tree is used. This bus supports NANDs, external ethernet controller,
SRAMs, ATA devices, etc.
config BRCMSTB_DPFE
bool "Broadcom STB DPFE driver" if COMPILE_TEST
default y if ARCH_BRCMSTB
depends on ARCH_BRCMSTB || COMPILE_TEST
help
This driver provides access to the DPFE interface of Broadcom
STB SoCs. The firmware running on the DCPU inside the DDR PHY can
provide current information about the system's RAM, for instance
the DRAM refresh rate. This can be used as an indirect indicator
for the DRAM's temperature. Slower refresh rate means cooler RAM,
higher refresh rate means hotter RAM.
config BT1_L2_CTL
bool "Baikal-T1 CM2 L2-RAM Cache Control Block"
depends on MIPS_BAIKAL_T1 || COMPILE_TEST
......@@ -65,7 +79,8 @@ config BT1_L2_CTL
config TI_AEMIF
tristate "Texas Instruments AEMIF driver"
depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF
depends on ARCH_DAVINCI || ARCH_KEYSTONE || COMPILE_TEST
depends on OF
help
This driver is for the AEMIF module available in Texas Instruments
SoCs. AEMIF stands for Asynchronous External Memory Interface and
......@@ -76,7 +91,7 @@ config TI_AEMIF
config TI_EMIF
tristate "Texas Instruments EMIF driver"
depends on ARCH_OMAP2PLUS
depends on ARCH_OMAP2PLUS || COMPILE_TEST
select DDR
help
This driver is for the EMIF module available in Texas Instruments
......@@ -88,7 +103,8 @@ config TI_EMIF
temperature changes
config OMAP_GPMC
bool
bool "Texas Instruments OMAP SoC GPMC driver" if COMPILE_TEST
depends on OF_ADDRESS
select GPIOLIB
help
This driver is for the General Purpose Memory Controller (GPMC)
......@@ -112,7 +128,8 @@ config OMAP_GPMC_DEBUG
config TI_EMIF_SRAM
tristate "Texas Instruments EMIF SRAM driver"
depends on (SOC_AM33XX || SOC_AM43XX) && SRAM
depends on SOC_AM33XX || SOC_AM43XX || (ARM && COMPILE_TEST)
depends on SRAM
help
This driver is for the EMIF module available on Texas Instruments
AM33XX and AM43XX SoCs and is required for PM. Certain parts of
......@@ -122,8 +139,9 @@ config TI_EMIF_SRAM
config MVEBU_DEVBUS
bool "Marvell EBU Device Bus Controller"
default y
depends on PLAT_ORION && OF
default y if PLAT_ORION
depends on PLAT_ORION || COMPILE_TEST
depends on OF
help
This driver is for the Device Bus controller available in some
Marvell EBU SoCs such as Discovery (mv78xx0), Orion (88f5xxx) and
......@@ -132,7 +150,7 @@ config MVEBU_DEVBUS
config FSL_CORENET_CF
tristate "Freescale CoreNet Error Reporting"
depends on FSL_SOC_BOOKE
depends on FSL_SOC_BOOKE || COMPILE_TEST
help
Say Y for reporting of errors from the Freescale CoreNet
Coherency Fabric. Errors reported include accesses to
......@@ -141,7 +159,7 @@ config FSL_CORENET_CF
represents a coherency violation.
config FSL_IFC
bool
bool "Freescale IFC driver" if COMPILE_TEST
depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A || COMPILE_TEST
depends on HAS_IOMEM
......@@ -155,7 +173,7 @@ config JZ4780_NEMC
memory devices such as NAND and SRAM.
config MTK_SMI
bool
bool "Mediatek SoC Memory Controller driver" if COMPILE_TEST
depends on ARCH_MEDIATEK || COMPILE_TEST
help
This driver is for the Memory Controller module in MediaTek SoCs,
......@@ -164,7 +182,7 @@ config MTK_SMI
config DA8XX_DDRCTL
bool "Texas Instruments da8xx DDR2/mDDR driver"
depends on ARCH_DAVINCI_DA8XX
depends on ARCH_DAVINCI_DA8XX || COMPILE_TEST
help
This driver is for the DDR2/mDDR Memory Controller present on
Texas Instruments da8xx SoCs. It's used to tweak various memory
......@@ -172,16 +190,16 @@ config DA8XX_DDRCTL
config PL353_SMC
tristate "ARM PL35X Static Memory Controller(SMC) driver"
default y
default y if ARM
depends on ARM
depends on ARM_AMBA
depends on ARM_AMBA || COMPILE_TEST
help
This driver is for the ARM PL351/PL353 Static Memory
Controller(SMC) module.
config RENESAS_RPCIF
tristate "Renesas RPC-IF driver"
depends on ARCH_RENESAS
depends on ARCH_RENESAS || COMPILE_TEST
select REGMAP_MMIO
help
This supports Renesas R-Car Gen3 RPC-IF which provides either SPI
......
......@@ -10,7 +10,7 @@ endif
obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o
obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o
obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o
obj-$(CONFIG_ARCH_BRCMSTB) += brcmstb_dpfe.o
obj-$(CONFIG_BRCMSTB_DPFE) += brcmstb_dpfe.o
obj-$(CONFIG_BT1_L2_CTL) += bt1-l2-ctl.o
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
obj-$(CONFIG_TI_EMIF) += emif.o
......
......@@ -188,11 +188,6 @@ struct brcmstb_dpfe_priv {
struct mutex lock;
};
static const char * const error_text[] = {
"Success", "Header code incorrect", "Unknown command or argument",
"Incorrect checksum", "Malformed command", "Timed out",
};
/*
* Forward declaration of our sysfs attribute functions, so we can declare the
* attribute data structures early.
......@@ -307,6 +302,20 @@ static const struct dpfe_api dpfe_api_v3 = {
},
};
static const char *get_error_text(unsigned int i)
{
static const char * const error_text[] = {
"Success", "Header code incorrect",
"Unknown command or argument", "Incorrect checksum",
"Malformed command", "Timed out", "Unknown error",
};
if (unlikely(i >= ARRAY_SIZE(error_text)))
i = ARRAY_SIZE(error_text) - 1;
return error_text[i];
}
static bool is_dcpu_enabled(struct brcmstb_dpfe_priv *priv)
{
u32 val;
......@@ -445,7 +454,7 @@ static int __send_command(struct brcmstb_dpfe_priv *priv, unsigned int cmd,
}
if (resp != 0) {
mutex_unlock(&priv->lock);
return -ETIMEDOUT;
return -ffs(DCPU_RET_ERR_TIMEDOUT);
}
/* Compute checksum over the message */
......@@ -647,8 +656,10 @@ static int brcmstb_dpfe_download_firmware(struct brcmstb_dpfe_priv *priv)
return (ret == -ENOENT) ? -EPROBE_DEFER : ret;
ret = __verify_firmware(&init, fw);
if (ret)
return -EFAULT;
if (ret) {
ret = -EFAULT;
goto release_fw;
}
__disable_dcpu(priv);
......@@ -667,18 +678,20 @@ static int brcmstb_dpfe_download_firmware(struct brcmstb_dpfe_priv *priv)
ret = __write_firmware(priv->dmem, dmem, dmem_size, is_big_endian);
if (ret)
return ret;
goto release_fw;
ret = __write_firmware(priv->imem, imem, imem_size, is_big_endian);
if (ret)
return ret;
goto release_fw;
ret = __verify_fw_checksum(&init, priv, header, init.chksum);
if (ret)
return ret;
goto release_fw;
__enable_dcpu(priv);
return 0;
release_fw:
release_firmware(fw);
return ret;
}
static ssize_t generic_show(unsigned int command, u32 response[],
......@@ -691,7 +704,7 @@ static ssize_t generic_show(unsigned int command, u32 response[],
ret = __send_command(priv, command, response);
if (ret < 0)
return sprintf(buf, "ERROR: %s\n", error_text[-ret]);
return sprintf(buf, "ERROR: %s\n", get_error_text(-ret));
return 0;
}
......@@ -888,11 +901,8 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev)
}
ret = brcmstb_dpfe_download_firmware(priv);
if (ret) {
if (ret != -EPROBE_DEFER)
dev_err(dev, "Couldn't download firmware -- %d\n", ret);
return ret;
}
if (ret)
return dev_err_probe(dev, ret, "Couldn't download firmware\n");
ret = sysfs_create_groups(&pdev->dev.kobj, priv->dpfe_api->sysfs_attrs);
if (!ret)
......
......@@ -131,16 +131,7 @@ static int emif_regdump_show(struct seq_file *s, void *unused)
return 0;
}
static int emif_regdump_open(struct inode *inode, struct file *file)
{
return single_open(file, emif_regdump_show, inode->i_private);
}
static const struct file_operations emif_regdump_fops = {
.open = emif_regdump_open,
.read = seq_read,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(emif_regdump);
static int emif_mr4_show(struct seq_file *s, void *unused)
{
......@@ -150,48 +141,16 @@ static int emif_mr4_show(struct seq_file *s, void *unused)
return 0;
}
static int emif_mr4_open(struct inode *inode, struct file *file)
{
return single_open(file, emif_mr4_show, inode->i_private);
}
static const struct file_operations emif_mr4_fops = {
.open = emif_mr4_open,
.read = seq_read,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(emif_mr4);
static int __init_or_module emif_debugfs_init(struct emif_data *emif)
{
struct dentry *dentry;
int ret;
dentry = debugfs_create_dir(dev_name(emif->dev), NULL);
if (!dentry) {
ret = -ENOMEM;
goto err0;
}
emif->debugfs_root = dentry;
dentry = debugfs_create_file("regcache_dump", S_IRUGO,
emif->debugfs_root, emif, &emif_regdump_fops);
if (!dentry) {
ret = -ENOMEM;
goto err1;
}
dentry = debugfs_create_file("mr4", S_IRUGO,
emif->debugfs_root, emif, &emif_mr4_fops);
if (!dentry) {
ret = -ENOMEM;
goto err1;
}
emif->debugfs_root = debugfs_create_dir(dev_name(emif->dev), NULL);
debugfs_create_file("regcache_dump", S_IRUGO, emif->debugfs_root, emif,
&emif_regdump_fops);
debugfs_create_file("mr4", S_IRUGO, emif->debugfs_root, emif,
&emif_mr4_fops);
return 0;
err1:
debugfs_remove_recursive(emif->debugfs_root);
err0:
return ret;
}
static void __exit emif_debugfs_exit(struct emif_data *emif)
......
......@@ -211,10 +211,8 @@ static int ccf_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, ccf);
irq = platform_get_irq(pdev, 0);
if (!irq) {
dev_err(&pdev->dev, "%s: no irq\n", __func__);
return -ENXIO;
}
if (irq < 0)
return irq;
ret = devm_request_irq(&pdev->dev, irq, ccf_irq, 0, pdev->name, ccf);
if (ret) {
......
......@@ -19,6 +19,9 @@
/* mt8173 */
#define SMI_LARB_MMU_EN 0xf00
/* mt8167 */
#define MT8167_SMI_LARB_MMU_EN 0xfc0
/* mt2701 */
#define REG_SMI_SECUR_CON_BASE 0x5c0
......@@ -179,6 +182,13 @@ static void mtk_smi_larb_config_port_mt8173(struct device *dev)
writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
}
static void mtk_smi_larb_config_port_mt8167(struct device *dev)
{
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
writel(*larb->mmu, larb->base + MT8167_SMI_LARB_MMU_EN);
}
static void mtk_smi_larb_config_port_gen1(struct device *dev)
{
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
......@@ -226,6 +236,11 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = {
.config_port = mtk_smi_larb_config_port_mt8173,
};
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8167 = {
/* mt8167 do not need the port in larb */
.config_port = mtk_smi_larb_config_port_mt8167,
};
static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
.port_in_larb = {
LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
......@@ -254,6 +269,10 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = {
};
static const struct of_device_id mtk_smi_larb_of_ids[] = {
{
.compatible = "mediatek,mt8167-smi-larb",
.data = &mtk_smi_larb_mt8167
},
{
.compatible = "mediatek,mt8173-smi-larb",
.data = &mtk_smi_larb_mt8173
......@@ -418,6 +437,10 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
.compatible = "mediatek,mt8173-smi-common",
.data = &mtk_smi_common_gen2,
},
{
.compatible = "mediatek,mt8167-smi-common",
.data = &mtk_smi_common_gen2,
},
{
.compatible = "mediatek,mt2701-smi-common",
.data = &mtk_smi_common_gen1,
......
This diff is collapsed.
......@@ -199,10 +199,8 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
rpc->dirmap = NULL;
rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(rpc->rstc))
return PTR_ERR(rpc->rstc);
return 0;
return PTR_ERR_OR_ZERO(rpc->rstc);
}
EXPORT_SYMBOL(rpcif_sw_init);
......
This diff is collapsed.
......@@ -1060,19 +1060,7 @@ static int tegra_emc_debug_available_rates_show(struct seq_file *s,
return 0;
}
static int tegra_emc_debug_available_rates_open(struct inode *inode,
struct file *file)
{
return single_open(file, tegra_emc_debug_available_rates_show,
inode->i_private);
}
static const struct file_operations tegra_emc_debug_available_rates_fops = {
.open = tegra_emc_debug_available_rates_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(tegra_emc_debug_available_rates);
static int tegra_emc_debug_min_rate_get(void *data, u64 *rate)
{
......
......@@ -957,7 +957,6 @@ static const struct tegra_smmu_swgroup tegra124_swgroups[] = {
static const unsigned int tegra124_group_drm[] = {
TEGRA_SWGROUP_DC,
TEGRA_SWGROUP_DCB,
TEGRA_SWGROUP_GPU,
TEGRA_SWGROUP_VIC,
};
......
......@@ -172,14 +172,8 @@ static int tegra186_emc_probe(struct platform_device *pdev)
return -ENOMEM;
emc->bpmp = tegra_bpmp_get(&pdev->dev);
if (IS_ERR(emc->bpmp)) {
err = PTR_ERR(emc->bpmp);
if (err != -EPROBE_DEFER)
dev_err(&pdev->dev, "failed to get BPMP: %d\n", err);
return err;
}
if (IS_ERR(emc->bpmp))
return dev_err_probe(&pdev->dev, PTR_ERR(emc->bpmp), "failed to get BPMP\n");
emc->clk = devm_clk_get(&pdev->dev, "emc");
if (IS_ERR(emc->clk)) {
......
......@@ -501,7 +501,6 @@ static u32 tegra210_emc_r21021_periodic_compensation(struct tegra210_emc *emc)
emc_cfg_o = emc_readl(emc, EMC_CFG);
emc_cfg = emc_cfg_o & ~(EMC_CFG_DYN_SELF_REF |
EMC_CFG_DRAM_ACPD |
EMC_CFG_DRAM_CLKSTOP_PD |
EMC_CFG_DRAM_CLKSTOP_PD);
......@@ -1044,7 +1043,7 @@ static void tegra210_emc_r21021_set_clock(struct tegra210_emc *emc, u32 clksrc)
!opt_cc_short_zcal && opt_short_zcal) {
value = (value & ~(EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK <<
EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_SHIFT)) |
((zq_wait_long & EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK) <<
((zq_wait_long & EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK) <<
EMC_MRS_WAIT_CNT_SHORT_WAIT_SHIFT);
} else if (offset == EMC_ZCAL_INTERVAL && opt_zcal_en_cc) {
value = 0; /* EMC_ZCAL_INTERVAL reset value. */
......
......@@ -842,7 +842,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
},
.la = {
.reg = 0x3dc,
.shift = 0,
.shift = 16,
.mask = 0xff,
.def = 0x80,
},
......
......@@ -65,9 +65,10 @@ config RESET_HSDK
This enables the reset controller driver for HSDK board.
config RESET_IMX7
bool "i.MX7/8 Reset Driver" if COMPILE_TEST
tristate "i.MX7/8 Reset Driver"
depends on HAS_IOMEM
default SOC_IMX7D || (ARM64 && ARCH_MXC)
depends on SOC_IMX7D || (ARM64 && ARCH_MXC) || COMPILE_TEST
default y if SOC_IMX7D
select MFD_SYSCON
help
This enables the reset controller driver for i.MX7 SoCs.
......
......@@ -32,7 +32,8 @@ static LIST_HEAD(reset_lookup_list);
* @refcnt: Number of gets of this reset_control
* @acquired: Only one reset_control may be acquired for a given rcdev and id.
* @shared: Is this a shared (1), or an exclusive (0) reset_control?
* @deassert_cnt: Number of times this reset line has been deasserted
* @array: Is this an array of reset controls (1)?
* @deassert_count: Number of times this reset line has been deasserted
* @triggered_count: Number of times this reset line has been reset. Currently
* only used for shared resets, which means that the value
* will be either 0 or 1.
......
......@@ -8,7 +8,7 @@
*/
#include <linux/mfd/syscon.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
......@@ -178,6 +178,9 @@ static const struct imx7_src_signal imx8mq_src_signals[IMX8MQ_RESET_NUM] = {
[IMX8MQ_RESET_A53_SOC_DBG_RESET] = { SRC_A53RCR0, BIT(20) },
[IMX8MQ_RESET_A53_L2RESET] = { SRC_A53RCR0, BIT(21) },
[IMX8MQ_RESET_SW_NON_SCLR_M4C_RST] = { SRC_M4RCR, BIT(0) },
[IMX8MQ_RESET_SW_M4C_RST] = { SRC_M4RCR, BIT(1) },
[IMX8MQ_RESET_SW_M4P_RST] = { SRC_M4RCR, BIT(2) },
[IMX8MQ_RESET_M4_ENABLE] = { SRC_M4RCR, BIT(3) },
[IMX8MQ_RESET_OTG1_PHY_RESET] = { SRC_USBOPHY1_RCR, BIT(0) },
[IMX8MQ_RESET_OTG2_PHY_RESET] = { SRC_USBOPHY2_RCR, BIT(0) },
[IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N] = { SRC_MIPIPHY_RCR, BIT(1) },
......@@ -238,6 +241,7 @@ static int imx8mq_reset_set(struct reset_controller_dev *rcdev,
case IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N:
case IMX8MQ_RESET_MIPI_DSI_RESET_N:
case IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N:
case IMX8MQ_RESET_M4_ENABLE:
value = assert ? 0 : bit;
break;
}
......@@ -386,6 +390,7 @@ static const struct of_device_id imx7_reset_dt_ids[] = {
{ .compatible = "fsl,imx8mp-src", .data = &variant_imx8mp },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, imx7_reset_dt_ids);
static struct platform_driver imx7_reset_driver = {
.probe = imx7_reset_probe,
......@@ -394,4 +399,8 @@ static struct platform_driver imx7_reset_driver = {
.of_match_table = imx7_reset_dt_ids,
},
};
builtin_platform_driver(imx7_reset_driver);
module_platform_driver(imx7_reset_driver);
MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
MODULE_DESCRIPTION("NXP i.MX7 reset driver");
MODULE_LICENSE("GPL v2");
......@@ -9,12 +9,20 @@
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/firmware/xlnx-zynqmp.h>
#include <linux/of_device.h>
#define ZYNQMP_NR_RESETS (ZYNQMP_PM_RESET_END - ZYNQMP_PM_RESET_START)
#define ZYNQMP_RESET_ID ZYNQMP_PM_RESET_START
#define VERSAL_NR_RESETS 95
struct zynqmp_reset_soc_data {
u32 reset_id;
u32 num_resets;
};
struct zynqmp_reset_data {
struct reset_controller_dev rcdev;
const struct zynqmp_reset_soc_data *data;
};
static inline struct zynqmp_reset_data *
......@@ -26,23 +34,28 @@ to_zynqmp_reset_data(struct reset_controller_dev *rcdev)
static int zynqmp_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return zynqmp_pm_reset_assert(ZYNQMP_RESET_ID + id,
struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
return zynqmp_pm_reset_assert(priv->data->reset_id + id,
PM_RESET_ACTION_ASSERT);
}
static int zynqmp_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return zynqmp_pm_reset_assert(ZYNQMP_RESET_ID + id,
struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
return zynqmp_pm_reset_assert(priv->data->reset_id + id,
PM_RESET_ACTION_RELEASE);
}
static int zynqmp_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
int val, err;
err = zynqmp_pm_reset_get_status(ZYNQMP_RESET_ID + id, &val);
err = zynqmp_pm_reset_get_status(priv->data->reset_id + id, &val);
if (err)
return err;
......@@ -52,10 +65,28 @@ static int zynqmp_reset_status(struct reset_controller_dev *rcdev,
static int zynqmp_reset_reset(struct reset_controller_dev *rcdev,
unsigned long id)
{
return zynqmp_pm_reset_assert(ZYNQMP_RESET_ID + id,
struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
return zynqmp_pm_reset_assert(priv->data->reset_id + id,
PM_RESET_ACTION_PULSE);
}
static int zynqmp_reset_of_xlate(struct reset_controller_dev *rcdev,
const struct of_phandle_args *reset_spec)
{
return reset_spec->args[0];
}
static const struct zynqmp_reset_soc_data zynqmp_reset_data = {
.reset_id = ZYNQMP_RESET_ID,
.num_resets = ZYNQMP_NR_RESETS,
};
static const struct zynqmp_reset_soc_data versal_reset_data = {
.reset_id = 0,
.num_resets = VERSAL_NR_RESETS,
};
static const struct reset_control_ops zynqmp_reset_ops = {
.reset = zynqmp_reset_reset,
.assert = zynqmp_reset_assert,
......@@ -71,18 +102,25 @@ static int zynqmp_reset_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
priv->data = of_device_get_match_data(&pdev->dev);
if (!priv->data)
return -EINVAL;
platform_set_drvdata(pdev, priv);
priv->rcdev.ops = &zynqmp_reset_ops;
priv->rcdev.owner = THIS_MODULE;
priv->rcdev.of_node = pdev->dev.of_node;
priv->rcdev.nr_resets = ZYNQMP_NR_RESETS;
priv->rcdev.nr_resets = priv->data->num_resets;
priv->rcdev.of_reset_n_cells = 1;
priv->rcdev.of_xlate = zynqmp_reset_of_xlate;
return devm_reset_controller_register(&pdev->dev, &priv->rcdev);
}
static const struct of_device_id zynqmp_reset_dt_ids[] = {
{ .compatible = "xlnx,zynqmp-reset", },
{ .compatible = "xlnx,zynqmp-reset", .data = &zynqmp_reset_data, },
{ .compatible = "xlnx,versal-reset", .data = &versal_reset_data, },
{ /* sentinel */ },
};
......
......@@ -17,7 +17,7 @@
#include "reset-syscfg.h"
/**
* Reset channel regmap configuration
* struct syscfg_reset_channel - Reset channel regmap configuration
*
* @reset: regmap field for the channel's reset bit.
* @ack: regmap field for the channel's ack bit (optional).
......@@ -28,8 +28,9 @@ struct syscfg_reset_channel {
};
/**
* A reset controller which groups together a set of related reset bits, which
* may be located in different system configuration registers.
* struct syscfg_reset_controller - A reset controller which groups together
* a set of related reset bits, which may be located in different system
* configuration registers.
*
* @rst: base reset controller structure.
* @active_low: are the resets in this controller active low, i.e. clearing
......
......@@ -15,6 +15,7 @@
#include <linux/reset.h>
#include <linux/clk.h>
#include <dt-bindings/power/meson8-power.h>
#include <dt-bindings/power/meson-axg-power.h>
#include <dt-bindings/power/meson-g12a-power.h>
#include <dt-bindings/power/meson-gxbb-power.h>
#include <dt-bindings/power/meson-sm1-power.h>
......@@ -134,6 +135,11 @@ static struct meson_ee_pwrc_top_domain sm1_pwrc_ge2d = SM1_EE_PD(19);
{ __reg, BIT(14) }, \
{ __reg, BIT(15) }
static struct meson_ee_pwrc_mem_domain axg_pwrc_mem_vpu[] = {
VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
};
static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_vpu[] = {
VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
......@@ -190,6 +196,10 @@ static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_ge2d[] = {
{ HHI_MEM_PD_REG0, GENMASK(25, 18) },
};
static struct meson_ee_pwrc_mem_domain axg_pwrc_mem_audio[] = {
{ HHI_MEM_PD_REG0, GENMASK(5, 4) },
};
static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = {
{ HHI_MEM_PD_REG0, GENMASK(5, 4) },
{ HHI_AUDIO_MEM_PD_REG0, GENMASK(1, 0) },
......@@ -231,6 +241,13 @@ static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = {
static bool pwrc_ee_get_power(struct meson_ee_pwrc_domain *pwrc_domain);
static struct meson_ee_pwrc_domain_desc axg_pwrc_domains[] = {
[PWRC_AXG_VPU_ID] = VPU_PD("VPU", &gx_pwrc_vpu, axg_pwrc_mem_vpu,
pwrc_ee_get_power, 5, 2),
[PWRC_AXG_ETHERNET_MEM_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
[PWRC_AXG_AUDIO_ID] = MEM_PD("AUDIO", axg_pwrc_mem_audio),
};
static struct meson_ee_pwrc_domain_desc g12a_pwrc_domains[] = {
[PWRC_G12A_VPU_ID] = VPU_PD("VPU", &gx_pwrc_vpu, g12a_pwrc_mem_vpu,
pwrc_ee_get_power, 11, 2),
......@@ -433,8 +450,8 @@ static int meson_ee_pwrc_init_domain(struct platform_device *pdev,
if (ret)
return ret;
ret = pm_genpd_init(&dom->base, &pm_domain_always_on_gov,
false);
dom->base.flags = GENPD_FLAG_ALWAYS_ON;
ret = pm_genpd_init(&dom->base, NULL, false);
if (ret)
return ret;
} else {
......@@ -529,6 +546,11 @@ static struct meson_ee_pwrc_domain_data meson_ee_g12a_pwrc_data = {
.domains = g12a_pwrc_domains,
};
static struct meson_ee_pwrc_domain_data meson_ee_axg_pwrc_data = {
.count = ARRAY_SIZE(axg_pwrc_domains),
.domains = axg_pwrc_domains,
};
static struct meson_ee_pwrc_domain_data meson_ee_gxbb_pwrc_data = {
.count = ARRAY_SIZE(gxbb_pwrc_domains),
.domains = gxbb_pwrc_domains,
......@@ -562,6 +584,10 @@ static const struct of_device_id meson_ee_pwrc_match_table[] = {
.compatible = "amlogic,meson8m2-pwrc",
.data = &meson_ee_m8b_pwrc_data,
},
{
.compatible = "amlogic,meson-axg-pwrc",
.data = &meson_ee_axg_pwrc_data,
},
{
.compatible = "amlogic,meson-gxbb-pwrc",
.data = &meson_ee_gxbb_pwrc_data,
......
......@@ -339,8 +339,8 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
return ret;
}
pm_genpd_init(&vpu_pd->genpd, &pm_domain_always_on_gov,
powered_off);
vpu_pd->genpd.flags = GENPD_FLAG_ALWAYS_ON;
pm_genpd_init(&vpu_pd->genpd, NULL, powered_off);
return of_genpd_add_provider_simple(pdev->dev.of_node,
&vpu_pd->genpd);
......
......@@ -22,6 +22,15 @@ config RASPBERRYPI_POWER
This enables support for the RPi power domains which can be enabled
or disabled via the RPi firmware.
config SOC_BCM63XX
bool "Broadcom 63xx SoC drivers"
depends on BMIPS_GENERIC || COMPILE_TEST
help
Enables drivers for the Broadcom 63xx series of chips.
Drivers can be enabled individually within this menu.
If unsure, say N.
config SOC_BRCMSTB
bool "Broadcom STB SoC drivers"
depends on ARM || ARM64 || BMIPS_GENERIC || COMPILE_TEST
......@@ -33,6 +42,7 @@ config SOC_BRCMSTB
If unsure, say N.
source "drivers/soc/bcm/bcm63xx/Kconfig"
source "drivers/soc/bcm/brcmstb/Kconfig"
endmenu
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o
obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o
obj-$(CONFIG_SOC_BCM63XX) += bcm63xx/
obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
# SPDX-License-Identifier: GPL-2.0-only
if SOC_BCM63XX
config BCM63XX_POWER
bool "BCM63xx power domain driver"
depends on BMIPS_GENERIC || (COMPILE_TEST && OF)
select PM_GENERIC_DOMAINS if PM
help
This enables support for the BCM63xx power domains controller on
BCM6318, BCM6328, BCM6362 and BCM63268 SoCs.
endif # SOC_BCM63XX
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_BCM63XX_POWER) += bcm63xx-power.o
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* BCM63xx Power Domain Controller Driver
*
* Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
*/
#include <dt-bindings/soc/bcm6318-pm.h>
#include <dt-bindings/soc/bcm6328-pm.h>
#include <dt-bindings/soc/bcm6362-pm.h>
#include <dt-bindings/soc/bcm63268-pm.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/of.h>
#include <linux/of_device.h>
struct bcm63xx_power_dev {
struct generic_pm_domain genpd;
struct bcm63xx_power *power;
uint32_t mask;
};
struct bcm63xx_power {
void __iomem *base;
spinlock_t lock;
struct bcm63xx_power_dev *dev;
struct genpd_onecell_data genpd_data;
struct generic_pm_domain **genpd;
};
struct bcm63xx_power_data {
const char * const name;
uint8_t bit;
unsigned int flags;
};
static int bcm63xx_power_get_state(struct bcm63xx_power_dev *pmd, bool *is_on)
{
struct bcm63xx_power *power = pmd->power;
if (!pmd->mask) {
*is_on = false;
return -EINVAL;
}
*is_on = !(__raw_readl(power->base) & pmd->mask);
return 0;
}
static int bcm63xx_power_set_state(struct bcm63xx_power_dev *pmd, bool on)
{
struct bcm63xx_power *power = pmd->power;
unsigned long flags;
uint32_t val;
if (!pmd->mask)
return -EINVAL;
spin_lock_irqsave(&power->lock, flags);
val = __raw_readl(power->base);
if (on)
val &= ~pmd->mask;
else
val |= pmd->mask;
__raw_writel(val, power->base);
spin_unlock_irqrestore(&power->lock, flags);
return 0;
}
static int bcm63xx_power_on(struct generic_pm_domain *genpd)
{
struct bcm63xx_power_dev *pmd = container_of(genpd,
struct bcm63xx_power_dev, genpd);
return bcm63xx_power_set_state(pmd, true);
}
static int bcm63xx_power_off(struct generic_pm_domain *genpd)
{
struct bcm63xx_power_dev *pmd = container_of(genpd,
struct bcm63xx_power_dev, genpd);
return bcm63xx_power_set_state(pmd, false);
}
static int bcm63xx_power_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct resource *res;
const struct bcm63xx_power_data *entry, *table;
struct bcm63xx_power *power;
unsigned int ndom;
uint8_t max_bit = 0;
int ret;
power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
if (!power)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
power->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(power->base))
return PTR_ERR(power->base);
table = of_device_get_match_data(dev);
if (!table)
return -EINVAL;
power->genpd_data.num_domains = 0;
ndom = 0;
for (entry = table; entry->name; entry++) {
max_bit = max(max_bit, entry->bit);
ndom++;
}
if (!ndom)
return -ENODEV;
power->genpd_data.num_domains = max_bit + 1;
power->dev = devm_kcalloc(dev, power->genpd_data.num_domains,
sizeof(struct bcm63xx_power_dev),
GFP_KERNEL);
if (!power->dev)
return -ENOMEM;
power->genpd = devm_kcalloc(dev, power->genpd_data.num_domains,
sizeof(struct generic_pm_domain *),
GFP_KERNEL);
if (!power->genpd)
return -ENOMEM;
power->genpd_data.domains = power->genpd;
ndom = 0;
for (entry = table; entry->name; entry++) {
struct bcm63xx_power_dev *pmd = &power->dev[ndom];
bool is_on;
pmd->power = power;
pmd->mask = BIT(entry->bit);
pmd->genpd.name = entry->name;
pmd->genpd.flags = entry->flags;
ret = bcm63xx_power_get_state(pmd, &is_on);
if (ret)
dev_warn(dev, "unable to get current state for %s\n",
pmd->genpd.name);
pmd->genpd.power_on = bcm63xx_power_on;
pmd->genpd.power_off = bcm63xx_power_off;
pm_genpd_init(&pmd->genpd, NULL, !is_on);
power->genpd[entry->bit] = &pmd->genpd;
ndom++;
}
spin_lock_init(&power->lock);
ret = of_genpd_add_provider_onecell(np, &power->genpd_data);
if (ret) {
dev_err(dev, "failed to register genpd driver: %d\n", ret);
return ret;
}
dev_info(dev, "registered %u power domains\n", ndom);
return 0;
}
static const struct bcm63xx_power_data bcm6318_power_domains[] = {
{
.name = "pcie",
.bit = BCM6318_POWER_DOMAIN_PCIE,
}, {
.name = "usb",
.bit = BCM6318_POWER_DOMAIN_USB,
}, {
.name = "ephy0",
.bit = BCM6318_POWER_DOMAIN_EPHY0,
}, {
.name = "ephy1",
.bit = BCM6318_POWER_DOMAIN_EPHY1,
}, {
.name = "ephy2",
.bit = BCM6318_POWER_DOMAIN_EPHY2,
}, {
.name = "ephy3",
.bit = BCM6318_POWER_DOMAIN_EPHY3,
}, {
.name = "ldo2p5",
.bit = BCM6318_POWER_DOMAIN_LDO2P5,
.flags = GENPD_FLAG_ALWAYS_ON,
}, {
.name = "ldo2p9",
.bit = BCM6318_POWER_DOMAIN_LDO2P9,
.flags = GENPD_FLAG_ALWAYS_ON,
}, {
.name = "sw1p0",
.bit = BCM6318_POWER_DOMAIN_SW1P0,
.flags = GENPD_FLAG_ALWAYS_ON,
}, {
.name = "pad",
.bit = BCM6318_POWER_DOMAIN_PAD,
.flags = GENPD_FLAG_ALWAYS_ON,
}, {
/* sentinel */
},
};
static const struct bcm63xx_power_data bcm6328_power_domains[] = {
{
.name = "adsl2-mips",
.bit = BCM6328_POWER_DOMAIN_ADSL2_MIPS,
}, {
.name = "adsl2-phy",
.bit = BCM6328_POWER_DOMAIN_ADSL2_PHY,
}, {
.name = "adsl2-afe",
.bit = BCM6328_POWER_DOMAIN_ADSL2_AFE,
}, {
.name = "sar",
.bit = BCM6328_POWER_DOMAIN_SAR,
}, {
.name = "pcm",
.bit = BCM6328_POWER_DOMAIN_PCM,
}, {
.name = "usbd",
.bit = BCM6328_POWER_DOMAIN_USBD,
}, {
.name = "usbh",
.bit = BCM6328_POWER_DOMAIN_USBH,
}, {
.name = "pcie",
.bit = BCM6328_POWER_DOMAIN_PCIE,
}, {
.name = "robosw",
.bit = BCM6328_POWER_DOMAIN_ROBOSW,
}, {
.name = "ephy",
.bit = BCM6328_POWER_DOMAIN_EPHY,
}, {
/* sentinel */
},
};
static const struct bcm63xx_power_data bcm6362_power_domains[] = {
{
.name = "sar",
.bit = BCM6362_POWER_DOMAIN_SAR,
}, {
.name = "ipsec",
.bit = BCM6362_POWER_DOMAIN_IPSEC,
}, {
.name = "mips",
.bit = BCM6362_POWER_DOMAIN_MIPS,
.flags = GENPD_FLAG_ALWAYS_ON,
}, {
.name = "dect",
.bit = BCM6362_POWER_DOMAIN_DECT,
}, {
.name = "usbh",
.bit = BCM6362_POWER_DOMAIN_USBH,
}, {
.name = "usbd",
.bit = BCM6362_POWER_DOMAIN_USBD,
}, {
.name = "robosw",
.bit = BCM6362_POWER_DOMAIN_ROBOSW,
}, {
.name = "pcm",
.bit = BCM6362_POWER_DOMAIN_PCM,
}, {
.name = "periph",
.bit = BCM6362_POWER_DOMAIN_PERIPH,
.flags = GENPD_FLAG_ALWAYS_ON,
}, {
.name = "adsl-phy",
.bit = BCM6362_POWER_DOMAIN_ADSL_PHY,
}, {
.name = "gmii-pads",
.bit = BCM6362_POWER_DOMAIN_GMII_PADS,
}, {
.name = "fap",
.bit = BCM6362_POWER_DOMAIN_FAP,
}, {
.name = "pcie",
.bit = BCM6362_POWER_DOMAIN_PCIE,
}, {
.name = "wlan-pads",
.bit = BCM6362_POWER_DOMAIN_WLAN_PADS,
}, {
/* sentinel */
},
};
static const struct bcm63xx_power_data bcm63268_power_domains[] = {
{
.name = "sar",
.bit = BCM63268_POWER_DOMAIN_SAR,
}, {
.name = "ipsec",
.bit = BCM63268_POWER_DOMAIN_IPSEC,
}, {
.name = "mips",
.bit = BCM63268_POWER_DOMAIN_MIPS,
.flags = GENPD_FLAG_ALWAYS_ON,
}, {
.name = "dect",
.bit = BCM63268_POWER_DOMAIN_DECT,
}, {
.name = "usbh",
.bit = BCM63268_POWER_DOMAIN_USBH,
}, {
.name = "usbd",
.bit = BCM63268_POWER_DOMAIN_USBD,
}, {
.name = "robosw",
.bit = BCM63268_POWER_DOMAIN_ROBOSW,
}, {
.name = "pcm",
.bit = BCM63268_POWER_DOMAIN_PCM,
}, {
.name = "periph",
.bit = BCM63268_POWER_DOMAIN_PERIPH,
.flags = GENPD_FLAG_ALWAYS_ON,
}, {
.name = "vdsl-phy",
.bit = BCM63268_POWER_DOMAIN_VDSL_PHY,
}, {
.name = "vdsl-mips",
.bit = BCM63268_POWER_DOMAIN_VDSL_MIPS,
}, {
.name = "fap",
.bit = BCM63268_POWER_DOMAIN_FAP,
}, {
.name = "pcie",
.bit = BCM63268_POWER_DOMAIN_PCIE,
}, {
.name = "wlan-pads",
.bit = BCM63268_POWER_DOMAIN_WLAN_PADS,
}, {
/* sentinel */
},
};
static const struct of_device_id bcm63xx_power_of_match[] = {
{
.compatible = "brcm,bcm6318-power-controller",
.data = &bcm6318_power_domains,
}, {
.compatible = "brcm,bcm6328-power-controller",
.data = &bcm6328_power_domains,
}, {
.compatible = "brcm,bcm6362-power-controller",
.data = &bcm6362_power_domains,
}, {
.compatible = "brcm,bcm63268-power-controller",
.data = &bcm63268_power_domains,
}, {
/* sentinel */
}
};
static struct platform_driver bcm63xx_power_driver = {
.driver = {
.name = "bcm63xx-power-controller",
.of_match_table = bcm63xx_power_of_match,
},
.probe = bcm63xx_power_probe,
};
builtin_platform_driver(bcm63xx_power_driver);
......@@ -13,6 +13,22 @@
#include <linux/syscore_ops.h>
#include <linux/soc/brcmstb/brcmstb.h>
#define RACENPREF_MASK 0x3
#define RACPREFINST_SHIFT 0
#define RACENINST_SHIFT 2
#define RACPREFDATA_SHIFT 4
#define RACENDATA_SHIFT 6
#define RAC_CPU_SHIFT 8
#define RACCFG_MASK 0xff
#define DPREF_LINE_2_SHIFT 24
#define DPREF_LINE_2_MASK 0xff
/* Bitmask to enable instruction and data prefetching with a 256-bytes stride */
#define RAC_DATA_INST_EN_MASK (1 << RACPREFINST_SHIFT | \
RACENPREF_MASK << RACENINST_SHIFT | \
1 << RACPREFDATA_SHIFT | \
RACENPREF_MASK << RACENDATA_SHIFT)
#define CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK 0x70000000
#define CPU_CREDIT_REG_MCPx_READ_CRED_MASK 0xf
#define CPU_CREDIT_REG_MCPx_WRITE_CRED_MASK 0xf
......@@ -31,11 +47,21 @@ static void __iomem *cpubiuctrl_base;
static bool mcp_wr_pairing_en;
static const int *cpubiuctrl_regs;
enum cpubiuctrl_regs {
CPU_CREDIT_REG = 0,
CPU_MCP_FLOW_REG,
CPU_WRITEBACK_CTRL_REG,
RAC_CONFIG0_REG,
RAC_CONFIG1_REG,
NUM_CPU_BIUCTRL_REGS,
};
static inline u32 cbc_readl(int reg)
{
int offset = cpubiuctrl_regs[reg];
if (offset == -1)
if (offset == -1 ||
(IS_ENABLED(CONFIG_CACHE_B15_RAC) && reg >= RAC_CONFIG0_REG))
return (u32)-1;
return readl_relaxed(cpubiuctrl_base + offset);
......@@ -45,22 +71,19 @@ static inline void cbc_writel(u32 val, int reg)
{
int offset = cpubiuctrl_regs[reg];
if (offset == -1)
if (offset == -1 ||
(IS_ENABLED(CONFIG_CACHE_B15_RAC) && reg >= RAC_CONFIG0_REG))
return;
writel(val, cpubiuctrl_base + offset);
}
enum cpubiuctrl_regs {
CPU_CREDIT_REG = 0,
CPU_MCP_FLOW_REG,
CPU_WRITEBACK_CTRL_REG
};
static const int b15_cpubiuctrl_regs[] = {
[CPU_CREDIT_REG] = 0x184,
[CPU_MCP_FLOW_REG] = -1,
[CPU_WRITEBACK_CTRL_REG] = -1,
[RAC_CONFIG0_REG] = -1,
[RAC_CONFIG1_REG] = -1,
};
/* Odd cases, e.g: 7260A0 */
......@@ -68,22 +91,26 @@ static const int b53_cpubiuctrl_no_wb_regs[] = {
[CPU_CREDIT_REG] = 0x0b0,
[CPU_MCP_FLOW_REG] = 0x0b4,
[CPU_WRITEBACK_CTRL_REG] = -1,
[RAC_CONFIG0_REG] = 0x78,
[RAC_CONFIG1_REG] = 0x7c,
};
static const int b53_cpubiuctrl_regs[] = {
[CPU_CREDIT_REG] = 0x0b0,
[CPU_MCP_FLOW_REG] = 0x0b4,
[CPU_WRITEBACK_CTRL_REG] = 0x22c,
[RAC_CONFIG0_REG] = 0x78,
[RAC_CONFIG1_REG] = 0x7c,
};
static const int a72_cpubiuctrl_regs[] = {
[CPU_CREDIT_REG] = 0x18,
[CPU_MCP_FLOW_REG] = 0x1c,
[CPU_WRITEBACK_CTRL_REG] = 0x20,
[RAC_CONFIG0_REG] = 0x08,
[RAC_CONFIG1_REG] = 0x0c,
};
#define NUM_CPU_BIUCTRL_REGS 3
static int __init mcp_write_pairing_set(void)
{
u32 creds = 0;
......@@ -110,6 +137,8 @@ static int __init mcp_write_pairing_set(void)
static const u32 a72_b53_mach_compat[] = {
0x7211,
0x7216,
0x72164,
0x72165,
0x7255,
0x7260,
0x7268,
......@@ -117,6 +146,61 @@ static const u32 a72_b53_mach_compat[] = {
0x7278,
};
/* The read-ahead cache present in the Brahma-B53 CPU is a special piece of
* hardware after the integrated L2 cache of the B53 CPU complex whose purpose
* is to prefetch instruction and/or data with a line size of either 64 bytes
* or 256 bytes. The rationale is that the data-bus of the CPU interface is
* optimized for 256-byte transactions, and enabling the read-ahead cache
* provides a significant performance boost (typically twice the performance
* for a memcpy benchmark application).
*
* The read-ahead cache is transparent for Virtual Address cache maintenance
* operations: IC IVAU, DC IVAC, DC CVAC, DC CVAU and DC CIVAC. So no special
* handling is needed for the DMA API above and beyond what is included in the
* arm64 implementation.
*
* In addition, since the Point of Unification is typically between L1 and L2
* for the Brahma-B53 processor no special read-ahead cache handling is needed
* for the IC IALLU and IC IALLUIS cache maintenance operations.
*
* However, it is not possible to specify the cache level (L3) for the cache
* maintenance instructions operating by set/way to operate on the read-ahead
* cache. The read-ahead cache will maintain coherency when inner cache lines
* are cleaned by set/way, but if it is necessary to invalidate inner cache
* lines by set/way to maintain coherency with system masters operating on
* shared memory that does not have hardware support for coherency, then it
* will also be necessary to explicitly invalidate the read-ahead cache.
*/
static void __init a72_b53_rac_enable_all(struct device_node *np)
{
unsigned int cpu;
u32 enable = 0, pref_dist, shift;
if (IS_ENABLED(CONFIG_CACHE_B15_RAC))
return;
if (WARN(num_possible_cpus() > 4, "RAC only supports 4 CPUs\n"))
return;
pref_dist = cbc_readl(RAC_CONFIG1_REG);
for_each_possible_cpu(cpu) {
shift = cpu * RAC_CPU_SHIFT + RACPREFDATA_SHIFT;
enable |= RAC_DATA_INST_EN_MASK << (cpu * RAC_CPU_SHIFT);
if (cpubiuctrl_regs == a72_cpubiuctrl_regs) {
enable &= ~(RACENPREF_MASK << shift);
enable |= 3 << shift;
pref_dist |= 1 << (cpu + DPREF_LINE_2_SHIFT);
}
}
cbc_writel(enable, RAC_CONFIG0_REG);
cbc_writel(pref_dist, RAC_CONFIG1_REG);
pr_info("%pOF: Broadcom %s read-ahead cache\n",
np, cpubiuctrl_regs == a72_cpubiuctrl_regs ?
"Cortex-A72" : "Brahma-B53");
}
static void __init mcp_a72_b53_set(void)
{
unsigned int i;
......@@ -262,6 +346,7 @@ static int __init brcmstb_biuctrl_init(void)
return ret;
}
a72_b53_rac_enable_all(np);
mcp_a72_b53_set();
#ifdef CONFIG_PM_SLEEP
register_syscore_ops(&brcmstb_cpu_credit_syscore_ops);
......
......@@ -647,7 +647,6 @@ int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s,
const uint32_t *cl = (uint32_t *)d;
uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
int i, num_enqueued = 0;
uint64_t addr_cena;
spin_lock(&s->access_spinlock);
half_mask = (s->eqcr.pi_ci_mask>>1);
......@@ -701,7 +700,6 @@ int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s,
/* Flush all the cacheline without load/store in between */
eqcr_pi = s->eqcr.pi;
addr_cena = (size_t)s->addr_cena;
for (i = 0; i < num_enqueued; i++)
eqcr_pi++;
s->eqcr.pi = eqcr_pi & full_mask;
......
......@@ -660,7 +660,7 @@ int bm_shutdown_pool(u32 bpid)
}
done:
put_affine_portal();
return 0;
return err;
}
struct gen_pool *bm_bpalloc;
......
......@@ -86,7 +86,7 @@ static void fd_inc(struct qm_fd *fd)
len--;
qm_fd_set_param(fd, fmt, off, len);
fd->cmd = cpu_to_be32(be32_to_cpu(fd->cmd) + 1);
be32_add_cpu(&fd->cmd, 1);
}
/* The only part of the 'fd' we can't memcmp() is the ppid */
......
......@@ -523,7 +523,7 @@ int ucc_set_tdm_rxtx_clk(u32 tdm_num, enum qe_clock clock,
qe_mux_reg = &qe_immr->qmx;
if (tdm_num > 7 || tdm_num < 0)
if (tdm_num > 7)
return -EINVAL;
/* The communications direction must be RX or TX */
......
......@@ -487,22 +487,17 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
domain->regulator = devm_regulator_get_optional(domain->dev, "power");
if (IS_ERR(domain->regulator)) {
if (PTR_ERR(domain->regulator) != -ENODEV) {
if (PTR_ERR(domain->regulator) != -EPROBE_DEFER)
dev_err(domain->dev, "Failed to get domain's regulator\n");
return PTR_ERR(domain->regulator);
}
if (PTR_ERR(domain->regulator) != -ENODEV)
return dev_err_probe(domain->dev, PTR_ERR(domain->regulator),
"Failed to get domain's regulator\n");
} else if (domain->voltage) {
regulator_set_voltage(domain->regulator,
domain->voltage, domain->voltage);
}
ret = imx_pgc_get_clocks(domain);
if (ret) {
if (ret != -EPROBE_DEFER)
dev_err(domain->dev, "Failed to get domain's clocks\n");
return ret;
}
if (ret)
return dev_err_probe(domain->dev, ret, "Failed to get domain's clocks\n");
ret = pm_genpd_init(&domain->genpd, NULL, true);
if (ret) {
......
......@@ -13,11 +13,16 @@
#define CMDQ_POLL_ENABLE_MASK BIT(0)
#define CMDQ_EOC_IRQ_EN BIT(0)
#define CMDQ_REG_TYPE 1
#define CMDQ_JUMP_RELATIVE 1
struct cmdq_instruction {
union {
u32 value;
u32 mask;
struct {
u16 arg_c;
u16 src_reg;
};
};
union {
u16 offset;
......@@ -223,15 +228,104 @@ int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys,
}
EXPORT_SYMBOL(cmdq_pkt_write_mask);
int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event)
int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low,
u16 reg_idx)
{
struct cmdq_instruction inst = {};
inst.op = CMDQ_CODE_READ_S;
inst.dst_t = CMDQ_REG_TYPE;
inst.sop = high_addr_reg_idx;
inst.reg_dst = reg_idx;
inst.src_reg = addr_low;
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_read_s);
int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
u16 addr_low, u16 src_reg_idx)
{
struct cmdq_instruction inst = {};
inst.op = CMDQ_CODE_WRITE_S;
inst.src_t = CMDQ_REG_TYPE;
inst.sop = high_addr_reg_idx;
inst.offset = addr_low;
inst.src_reg = src_reg_idx;
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_write_s);
int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
u16 addr_low, u16 src_reg_idx, u32 mask)
{
struct cmdq_instruction inst = {};
int err;
inst.op = CMDQ_CODE_MASK;
inst.mask = ~mask;
err = cmdq_pkt_append_command(pkt, inst);
if (err < 0)
return err;
inst.mask = 0;
inst.op = CMDQ_CODE_WRITE_S_MASK;
inst.src_t = CMDQ_REG_TYPE;
inst.sop = high_addr_reg_idx;
inst.offset = addr_low;
inst.src_reg = src_reg_idx;
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_write_s_mask);
int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx,
u16 addr_low, u32 value)
{
struct cmdq_instruction inst = {};
inst.op = CMDQ_CODE_WRITE_S;
inst.sop = high_addr_reg_idx;
inst.offset = addr_low;
inst.value = value;
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_write_s_value);
int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx,
u16 addr_low, u32 value, u32 mask)
{
struct cmdq_instruction inst = {};
int err;
inst.op = CMDQ_CODE_MASK;
inst.mask = ~mask;
err = cmdq_pkt_append_command(pkt, inst);
if (err < 0)
return err;
inst.op = CMDQ_CODE_WRITE_S_MASK;
inst.sop = high_addr_reg_idx;
inst.offset = addr_low;
inst.value = value;
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_write_s_mask_value);
int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear)
{
struct cmdq_instruction inst = { {0} };
u32 clear_option = clear ? CMDQ_WFE_UPDATE : 0;
if (event >= CMDQ_MAX_EVENT)
return -EINVAL;
inst.op = CMDQ_CODE_WFE;
inst.value = CMDQ_WFE_OPTION;
inst.value = CMDQ_WFE_OPTION | clear_option;
inst.event = event;
return cmdq_pkt_append_command(pkt, inst);
......@@ -315,6 +409,18 @@ int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value)
}
EXPORT_SYMBOL(cmdq_pkt_assign);
int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr)
{
struct cmdq_instruction inst = {};
inst.op = CMDQ_CODE_JUMP;
inst.offset = CMDQ_JUMP_RELATIVE;
inst.value = addr >>
cmdq_get_shift_pa(((struct cmdq_client *)pkt->cl)->chan);
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_jump);
int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
{
struct cmdq_instruction inst = { {0} };
......@@ -329,7 +435,8 @@ int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
/* JUMP to end */
inst.op = CMDQ_CODE_JUMP;
inst.value = CMDQ_JUMP_PASS;
inst.value = CMDQ_JUMP_PASS >>
cmdq_get_shift_pa(((struct cmdq_client *)pkt->cl)->chan);
err = cmdq_pkt_append_command(pkt, inst);
return err;
......
......@@ -19,7 +19,7 @@
/**
* mtk_infracfg_set_bus_protection - enable bus protection
* @regmap: The infracfg regmap
* @infracfg: The infracfg regmap
* @mask: The mask containing the protection bits to be enabled.
* @reg_update: The boolean flag determines to set the protection bits
* by regmap_update_bits with enable register(PROTECTEN) or
......@@ -50,7 +50,7 @@ int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
/**
* mtk_infracfg_clear_bus_protection - disable bus protection
* @regmap: The infracfg regmap
* @infracfg: The infracfg regmap
* @mask: The mask containing the protection bits to be disabled.
* @reg_update: The boolean flag determines to clear the protection bits
* by regmap_update_bits with enable register(PROTECTEN) or
......
......@@ -328,7 +328,7 @@ static int of_apr_add_pd_lookups(struct device *dev)
pds = pdr_add_lookup(apr->pdr, service_name, service_path);
if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
dev_err(dev, "pdr add lookup failed: %d\n", ret);
dev_err(dev, "pdr add lookup failed: %ld\n", PTR_ERR(pds));
return PTR_ERR(pds);
}
}
......
......@@ -387,7 +387,6 @@ static int qcom_llcc_remove(struct platform_device *pdev)
static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
const char *name)
{
struct resource *res;
void __iomem *base;
struct regmap_config llcc_regmap_config = {
.reg_bits = 32,
......@@ -396,11 +395,7 @@ static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
.fast_io = true,
};
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
if (!res)
return ERR_PTR(-ENODEV);
base = devm_ioremap_resource(&pdev->dev, res);
base = devm_platform_ioremap_resource_byname(pdev, name);
if (IS_ERR(base))
return ERR_CAST(base);
......
......@@ -8,6 +8,7 @@
#define __RPM_INTERNAL_H__
#include <linux/bitmap.h>
#include <linux/wait.h>
#include <soc/qcom/tcs.h>
#define TCS_TYPE_NR 4
......@@ -106,6 +107,8 @@ struct rpmh_ctrlr {
* @lock: Synchronize state of the controller. If RPMH's cache
* lock will also be held, the order is: drv->lock then
* cache_lock.
* @tcs_wait: Wait queue used to wait for @tcs_in_use to free up a
* slot
* @client: Handle to the DRV's client.
*/
struct rsc_drv {
......@@ -118,6 +121,7 @@ struct rsc_drv {
struct tcs_group tcs[TCS_TYPE_NR];
DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR);
spinlock_t lock;
wait_queue_head_t tcs_wait;
struct rpmh_ctrlr client;
};
......
......@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <soc/qcom/cmd-db.h>
#include <soc/qcom/tcs.h>
......@@ -453,6 +454,7 @@ static irqreturn_t tcs_tx_done(int irq, void *p)
if (!drv->tcs[ACTIVE_TCS].num_tcs)
enable_tcs_irq(drv, i, false);
spin_unlock(&drv->lock);
wake_up(&drv->tcs_wait);
if (req)
rpmh_tx_done(req, err);
}
......@@ -571,73 +573,34 @@ static int find_free_tcs(struct tcs_group *tcs)
}
/**
* tcs_write() - Store messages into a TCS right now, or return -EBUSY.
* claim_tcs_for_req() - Claim a tcs in the given tcs_group; only for active.
* @drv: The controller.
* @tcs: The tcs_group used for ACTIVE_ONLY transfers.
* @msg: The data to be sent.
*
* Grabs a TCS for ACTIVE_ONLY transfers and writes the messages to it.
* Claims a tcs in the given tcs_group while making sure that no existing cmd
* is in flight that would conflict with the one in @msg.
*
* If there are no free TCSes for ACTIVE_ONLY transfers or if a command for
* the same address is already transferring returns -EBUSY which means the
* client should retry shortly.
* Context: Must be called with the drv->lock held since that protects
* tcs_in_use.
*
* Return: 0 on success, -EBUSY if client should retry, or an error.
* Client should have interrupts enabled for a bit before retrying.
* Return: The id of the claimed tcs or -EBUSY if a matching msg is in flight
* or the tcs_group is full.
*/
static int tcs_write(struct rsc_drv *drv, const struct tcs_request *msg)
static int claim_tcs_for_req(struct rsc_drv *drv, struct tcs_group *tcs,
const struct tcs_request *msg)
{
struct tcs_group *tcs;
int tcs_id;
unsigned long flags;
int ret;
tcs = get_tcs_for_msg(drv, msg);
if (IS_ERR(tcs))
return PTR_ERR(tcs);
spin_lock_irqsave(&drv->lock, flags);
/*
* The h/w does not like if we send a request to the same address,
* when one is already in-flight or being processed.
*/
ret = check_for_req_inflight(drv, tcs, msg);
if (ret)
goto unlock;
ret = find_free_tcs(tcs);
if (ret < 0)
goto unlock;
tcs_id = ret;
tcs->req[tcs_id - tcs->offset] = msg;
set_bit(tcs_id, drv->tcs_in_use);
if (msg->state == RPMH_ACTIVE_ONLY_STATE && tcs->type != ACTIVE_TCS) {
/*
* Clear previously programmed WAKE commands in selected
* repurposed TCS to avoid triggering them. tcs->slots will be
* cleaned from rpmh_flush() by invoking rpmh_rsc_invalidate()
*/
write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, tcs_id, 0);
write_tcs_reg_sync(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, 0);
enable_tcs_irq(drv, tcs_id, true);
}
spin_unlock_irqrestore(&drv->lock, flags);
/*
* These two can be done after the lock is released because:
* - We marked "tcs_in_use" under lock.
* - Once "tcs_in_use" has been marked nobody else could be writing
* to these registers until the interrupt goes off.
* - The interrupt can't go off until we trigger w/ the last line
* of __tcs_set_trigger() below.
*/
__tcs_buffer_write(drv, tcs_id, 0, msg);
__tcs_set_trigger(drv, tcs_id, true);
return ret;
return 0;
unlock:
spin_unlock_irqrestore(&drv->lock, flags);
return ret;
return find_free_tcs(tcs);
}
/**
......@@ -664,18 +627,47 @@ static int tcs_write(struct rsc_drv *drv, const struct tcs_request *msg)
*/
int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
{
int ret;
struct tcs_group *tcs;
int tcs_id;
unsigned long flags;
do {
ret = tcs_write(drv, msg);
if (ret == -EBUSY) {
pr_info_ratelimited("TCS Busy, retrying RPMH message send: addr=%#x\n",
msg->cmds[0].addr);
udelay(10);
}
} while (ret == -EBUSY);
tcs = get_tcs_for_msg(drv, msg);
if (IS_ERR(tcs))
return PTR_ERR(tcs);
return ret;
spin_lock_irqsave(&drv->lock, flags);
/* Wait forever for a free tcs. It better be there eventually! */
wait_event_lock_irq(drv->tcs_wait,
(tcs_id = claim_tcs_for_req(drv, tcs, msg)) >= 0,
drv->lock);
tcs->req[tcs_id - tcs->offset] = msg;
set_bit(tcs_id, drv->tcs_in_use);
if (msg->state == RPMH_ACTIVE_ONLY_STATE && tcs->type != ACTIVE_TCS) {
/*
* Clear previously programmed WAKE commands in selected
* repurposed TCS to avoid triggering them. tcs->slots will be
* cleaned from rpmh_flush() by invoking rpmh_rsc_invalidate()
*/
write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, tcs_id, 0);
write_tcs_reg_sync(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, 0);
enable_tcs_irq(drv, tcs_id, true);
}
spin_unlock_irqrestore(&drv->lock, flags);
/*
* These two can be done after the lock is released because:
* - We marked "tcs_in_use" under lock.
* - Once "tcs_in_use" has been marked nobody else could be writing
* to these registers until the interrupt goes off.
* - The interrupt can't go off until we trigger w/ the last line
* of __tcs_set_trigger() below.
*/
__tcs_buffer_write(drv, tcs_id, 0, msg);
__tcs_set_trigger(drv, tcs_id, true);
return 0;
}
/**
......@@ -983,6 +975,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
return ret;
spin_lock_init(&drv->lock);
init_waitqueue_head(&drv->tcs_wait);
bitmap_zero(drv->tcs_in_use, MAX_TCS_NR);
irq = platform_get_irq(pdev, drv->id);
......
......@@ -194,6 +194,7 @@ static const struct soc_id soc_id[] = {
{ 186, "MSM8674" },
{ 194, "MSM8974PRO" },
{ 206, "MSM8916" },
{ 207, "MSM8994" },
{ 208, "APQ8074-AA" },
{ 209, "APQ8074-AB" },
{ 210, "APQ8074PRO" },
......@@ -214,6 +215,8 @@ static const struct soc_id soc_id[] = {
{ 248, "MSM8216" },
{ 249, "MSM8116" },
{ 250, "MSM8616" },
{ 251, "MSM8992" },
{ 253, "APQ8094" },
{ 291, "APQ8096" },
{ 305, "MSM8996SG" },
{ 310, "MSM8996AU" },
......@@ -223,6 +226,8 @@ static const struct soc_id soc_id[] = {
{ 321, "SDM845" },
{ 341, "SDA845" },
{ 356, "SM8250" },
{ 402, "IPQ6018" },
{ 425, "SC7180" },
};
static const char *socinfo_machine(struct device *dev, unsigned int id)
......
This diff is collapsed.
......@@ -24,6 +24,7 @@ obj-$(CONFIG_SYSC_R8A77970) += r8a77970-sysc.o
obj-$(CONFIG_SYSC_R8A77980) += r8a77980-sysc.o
obj-$(CONFIG_SYSC_R8A77990) += r8a77990-sysc.o
obj-$(CONFIG_SYSC_R8A77995) += r8a77995-sysc.o
obj-$(CONFIG_SYSC_R8A779A0) += r8a779a0-sysc.o
ifdef CONFIG_SMP
obj-$(CONFIG_ARCH_R9A06G032) += r9a06g032-smp.o
endif
......
This diff is collapsed.
......@@ -37,6 +37,10 @@ static const struct rst_config rcar_rst_gen3 __initconst = {
.modemr = 0x60,
};
static const struct rst_config rcar_rst_r8a779a0 __initconst = {
.modemr = 0x00, /* MODEMR0 and it has CPG related bits */
};
static const struct of_device_id rcar_rst_matches[] __initconst = {
/* RZ/G1 is handled like R-Car Gen2 */
{ .compatible = "renesas,r8a7742-rst", .data = &rcar_rst_gen2 },
......@@ -67,6 +71,8 @@ static const struct of_device_id rcar_rst_matches[] __initconst = {
{ .compatible = "renesas,r8a77980-rst", .data = &rcar_rst_gen3 },
{ .compatible = "renesas,r8a77990-rst", .data = &rcar_rst_gen3 },
{ .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen3 },
/* R-Car V3U */
{ .compatible = "renesas,r8a779a0-rst", .data = &rcar_rst_r8a779a0 },
{ /* sentinel */ }
};
......
......@@ -200,6 +200,11 @@ static const struct renesas_soc soc_rcar_d3 __initconst __maybe_unused = {
.id = 0x58,
};
static const struct renesas_soc soc_rcar_v3u __initconst __maybe_unused = {
.family = &fam_rcar_gen3,
.id = 0x59,
};
static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = {
.family = &fam_shmobile,
.id = 0x37,
......@@ -291,6 +296,9 @@ static const struct of_device_id renesas_socs[] __initconst = {
#ifdef CONFIG_ARCH_R8A77995
{ .compatible = "renesas,r8a77995", .data = &soc_rcar_d3 },
#endif
#ifdef CONFIG_ARCH_R8A779A0
{ .compatible = "renesas,r8a779a0", .data = &soc_rcar_v3u },
#endif
#ifdef CONFIG_ARCH_SH73A0
{ .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 },
#endif
......
......@@ -194,7 +194,7 @@ static const struct sunxi_sram_data *sunxi_sram_of_parse(struct device_node *nod
if (!data) {
ret = -EINVAL;
goto err;
};
}
for (func = data->func; func->func; func++) {
if (val == func->val) {
......
......@@ -49,6 +49,9 @@ static struct tegra_fuse *fuse = &(struct tegra_fuse) {
};
static const struct of_device_id tegra_fuse_match[] = {
#ifdef CONFIG_ARCH_TEGRA_234_SOC
{ .compatible = "nvidia,tegra234-efuse", .data = &tegra234_fuse_soc },
#endif
#ifdef CONFIG_ARCH_TEGRA_194_SOC
{ .compatible = "nvidia,tegra194-efuse", .data = &tegra194_fuse_soc },
#endif
......@@ -326,7 +329,8 @@ const struct attribute_group tegra_soc_attr_group = {
.attrs = tegra_soc_attr,
};
#ifdef CONFIG_ARCH_TEGRA_194_SOC
#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \
IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
static ssize_t platform_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
......@@ -336,7 +340,7 @@ static ssize_t platform_show(struct device *dev, struct device_attribute *attr,
* platform type is silicon and all other non-zero values indicate
* the type of simulation platform is being used.
*/
return sprintf(buf, "%d\n", (tegra_read_chipid() >> 20) & 0xf);
return sprintf(buf, "%d\n", tegra_get_platform());
}
static DEVICE_ATTR_RO(platform);
......
......@@ -356,3 +356,33 @@ const struct tegra_fuse_soc tegra194_fuse_soc = {
.soc_attr_group = &tegra194_soc_attr_group,
};
#endif
#if defined(CONFIG_ARCH_TEGRA_234_SOC)
static const struct nvmem_cell_lookup tegra234_fuse_lookups[] = {
{
.nvmem_name = "fuse",
.cell_name = "xusb-pad-calibration",
.dev_id = "3520000.padctl",
.con_id = "calibration",
}, {
.nvmem_name = "fuse",
.cell_name = "xusb-pad-calibration-ext",
.dev_id = "3520000.padctl",
.con_id = "calibration-ext",
},
};
static const struct tegra_fuse_info tegra234_fuse_info = {
.read = tegra30_fuse_read,
.size = 0x300,
.spare = 0x280,
};
const struct tegra_fuse_soc tegra234_fuse_soc = {
.init = tegra30_fuse_init,
.info = &tegra234_fuse_info,
.lookups = tegra234_fuse_lookups,
.num_lookups = ARRAY_SIZE(tegra234_fuse_lookups),
.soc_attr_group = &tegra194_soc_attr_group,
};
#endif
......@@ -115,9 +115,17 @@ extern const struct tegra_fuse_soc tegra210_fuse_soc;
extern const struct tegra_fuse_soc tegra186_fuse_soc;
#endif
#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \
IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
extern const struct attribute_group tegra194_soc_attr_group;
#endif
#ifdef CONFIG_ARCH_TEGRA_194_SOC
extern const struct tegra_fuse_soc tegra194_fuse_soc;
extern const struct attribute_group tegra194_soc_attr_group;
#endif
#ifdef CONFIG_ARCH_TEGRA_234_SOC
extern const struct tegra_fuse_soc tegra234_fuse_soc;
#endif
#endif
......@@ -47,6 +47,31 @@ u8 tegra_get_minor_rev(void)
return (tegra_read_chipid() >> 16) & 0xf;
}
u8 tegra_get_platform(void)
{
return (tegra_read_chipid() >> 20) & 0xf;
}
bool tegra_is_silicon(void)
{
switch (tegra_get_chip_id()) {
case TEGRA194:
case TEGRA234:
if (tegra_get_platform() == 0)
return true;
return false;
}
/*
* Chips prior to Tegra194 have a different way of determining whether
* they are silicon or not. Since we never supported simulation on the
* older Tegra chips, don't bother extracting the information and just
* report that we're running on silicon.
*/
return true;
}
u32 tegra_read_straps(void)
{
WARN(!chipid, "Tegra ABP MISC not yet available\n");
......@@ -70,6 +95,7 @@ static const struct of_device_id apbmisc_match[] __initconst = {
{ .compatible = "nvidia,tegra20-apbmisc", },
{ .compatible = "nvidia,tegra186-misc", },
{ .compatible = "nvidia,tegra194-misc", },
{ .compatible = "nvidia,tegra234-misc", },
{},
};
......
This diff is collapsed.
......@@ -101,6 +101,17 @@ config TI_K3_SOCINFO
platforms to provide information about the SoC family and
variant to user space.
config TI_PRUSS
tristate "TI PRU-ICSS Subsystem Platform drivers"
depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3
select MFD_SYSCON
help
TI PRU-ICSS Subsystem platform specific support.
Say Y or M here to support the Programmable Realtime Unit (PRU)
processors on various TI SoCs. It's safe to say N here if you're
not interested in the PRU or if you are unsure.
endif # SOC_TI
config TI_SCI_INTA_MSI_DOMAIN
......
......@@ -12,4 +12,5 @@ obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o
obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN) += ti_sci_inta_msi.o
obj-$(CONFIG_TI_K3_RINGACC) += k3-ringacc.o
obj-$(CONFIG_TI_K3_SOCINFO) += k3-socinfo.o
obj-$(CONFIG_TI_PRUSS) += pruss.o
obj-$(CONFIG_POWER_AVS_OMAP) += smartreflex.o
......@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/sys_soc.h>
#include <linux/soc/ti/k3-ringacc.h>
#include <linux/soc/ti/ti_sci_protocol.h>
#include <linux/soc/ti/ti_sci_inta_msi.h>
......@@ -208,6 +209,15 @@ struct k3_ringacc {
const struct k3_ringacc_ops *ops;
};
/**
* struct k3_ringacc - Rings accelerator SoC data
*
* @dma_ring_reset_quirk: DMA reset w/a enable
*/
struct k3_ringacc_soc_data {
unsigned dma_ring_reset_quirk:1;
};
static long k3_ringacc_ring_get_fifo_pos(struct k3_ring *ring)
{
return K3_RINGACC_FIFO_WINDOW_SIZE_BYTES -
......@@ -1051,9 +1061,6 @@ static int k3_ringacc_probe_dt(struct k3_ringacc *ringacc)
return ret;
}
ringacc->dma_ring_reset_quirk =
of_property_read_bool(node, "ti,dma-ring-reset-quirk");
ringacc->tisci = ti_sci_get_by_phandle(node, "ti,sci");
if (IS_ERR(ringacc->tisci)) {
ret = PTR_ERR(ringacc->tisci);
......@@ -1084,9 +1091,22 @@ static int k3_ringacc_probe_dt(struct k3_ringacc *ringacc)
ringacc->rm_gp_range);
}
static const struct k3_ringacc_soc_data k3_ringacc_soc_data_sr1 = {
.dma_ring_reset_quirk = 1,
};
static const struct soc_device_attribute k3_ringacc_socinfo[] = {
{ .family = "AM65X",
.revision = "SR1.0",
.data = &k3_ringacc_soc_data_sr1
},
{/* sentinel */}
};
static int k3_ringacc_init(struct platform_device *pdev,
struct k3_ringacc *ringacc)
{
const struct soc_device_attribute *soc;
void __iomem *base_fifo, *base_rt;
struct device *dev = &pdev->dev;
struct resource *res;
......@@ -1103,6 +1123,13 @@ static int k3_ringacc_init(struct platform_device *pdev,
if (ret)
return ret;
soc = soc_device_match(k3_ringacc_socinfo);
if (soc && soc->data) {
const struct k3_ringacc_soc_data *soc_data = soc->data;
ringacc->dma_ring_reset_quirk = soc_data->dma_ring_reset_quirk;
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rt");
base_rt = devm_ioremap_resource(dev, res);
if (IS_ERR(base_rt))
......
......@@ -39,6 +39,7 @@ static const struct k3_soc_id {
} k3_soc_ids[] = {
{ 0xBB5A, "AM65X" },
{ 0xBB64, "J721E" },
{ 0xBB6D, "J7200" },
};
static int
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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