Commit 399eb9b6 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 driver updates from Arnd Bergmann:
 "This contains driver changes that are tightly connected to SoC
  specific code. Aside from smaller cleanups and bug fixes, here is a
  list of the notable changes.

  New device drivers:

   - The Turris Mox router has a new "moxtet" bus driver for its
     on-board pluggable extension bus. The same platform also gains a
     firmware driver.

   - The Samsung Exynos family gains a new Chipid driver exporting using
     the soc device sysfs interface

   - A similar socinfo driver for Qualcomm Snapdragon chips.

   - A firmware driver for the NXP i.MX DSP IPC protocol using shared
     memory and a mailbox

  Other changes:

   - The i.MX reset controller driver now supports the NXP i.MX8MM chip

   - Amlogic SoC specific drivers gain support for the S905X3 and A311D
     chips

   - A rework of the TI Davinci framebuffer driver to allow important
     cleanups in the platform code

   - A couple of device drivers for removed ARM SoC platforms are
     removed. Most of the removals were picked up by other maintainers,
     this contains whatever was left"

* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (123 commits)
  bus: uniphier-system-bus: use devm_platform_ioremap_resource()
  soc: ti: ti_sci_pm_domains: Add support for exclusive and shared access
  dt-bindings: ti_sci_pm_domains: Add support for exclusive and shared access
  firmware: ti_sci: Allow for device shared and exclusive requests
  bus: imx-weim: remove incorrect __init annotations
  fbdev: remove w90x900/nuc900 platform drivers
  spi: remove w90x900 driver
  net: remove w90p910-ether driver
  net: remove ks8695 driver
  firmware: turris-mox-rwtm: Add sysfs documentation
  firmware: Add Turris Mox rWTM firmware driver
  dt-bindings: firmware: Document cznic,turris-mox-rwtm binding
  bus: moxtet: fix unsigned comparison to less than zero
  bus: moxtet: remove set but not used variable 'dummy'
  ARM: scoop: Use the right include
  dt-bindings: power: add Amlogic Everything-Else power domains bindings
  soc: amlogic: Add support for Everything-Else power domains controller
  fbdev: da8xx: use resource management for dma
  fbdev: da8xx-fb: drop a redundant if
  fbdev: da8xx-fb: use devm_platform_ioremap_resource()
  ...
parents 2b97c395 3dc8dcb0
What: /sys/kernel/debug/moxtet/input
Date: March 2019
KernelVersion: 5.3
Contact: Marek Behún <marek.behun@nic.cz>
Description: (R) Read input from the shift registers, in hexadecimal.
Returns N+1 bytes, where N is the number of Moxtet connected
modules. The first byte is from the CPU board itself.
Example: 101214
10: CPU board with SD card
12: 2 = PCIe module, 1 = IRQ not active
14: 4 = Peridot module, 1 = IRQ not active
What: /sys/kernel/debug/moxtet/output
Date: March 2019
KernelVersion: 5.3
Contact: Marek Behún <marek.behun@nic.cz>
Description: (RW) Read last written value to the shift registers, in
hexadecimal, or write values to the shift registers, also
in hexadecimal.
Example: 0102
01: 01 was last written, or is to be written, to the
first module's shift register
02: the same for second module
What: /sys/bus/moxtet/devices/moxtet-<name>.<addr>/module_description
Date: March 2019
KernelVersion: 5.3
Contact: Marek Behún <marek.behun@nic.cz>
Description: (R) Moxtet module description. Format: string
What: /sys/bus/moxtet/devices/moxtet-<name>.<addr>/module_id
Date: March 2019
KernelVersion: 5.3
Contact: Marek Behún <marek.behun@nic.cz>
Description: (R) Moxtet module ID. Format: %x
What: /sys/bus/moxtet/devices/moxtet-<name>.<addr>/module_name
Date: March 2019
KernelVersion: 5.3
Contact: Marek Behún <marek.behun@nic.cz>
Description: (R) Moxtet module name. Format: string
......@@ -26,6 +26,13 @@ Description:
Read-only attribute common to all SoCs. Contains SoC family name
(e.g. DB8500).
What: /sys/devices/socX/serial_number
Date: January 2019
contact: Bjorn Andersson <bjorn.andersson@linaro.org>
Description:
Read-only attribute supported by most SoCs. Contains the SoC's
serial number, if available.
What: /sys/devices/socX/soc_id
Date: January 2012
contact: Lee Jones <lee.jones@linaro.org>
......
What: /sys/firmware/turris-mox-rwtm/board_version
Date: August 2019
KernelVersion: 5.4
Contact: Marek Behún <marek.behun@nic.cz>
Description: (R) Board version burned into eFuses of this Turris Mox board.
Format: %i
What: /sys/firmware/turris-mox-rwtm/mac_address*
Date: August 2019
KernelVersion: 5.4
Contact: Marek Behún <marek.behun@nic.cz>
Description: (R) MAC addresses burned into eFuses of this Turris Mox board.
Format: %pM
What: /sys/firmware/turris-mox-rwtm/pubkey
Date: August 2019
KernelVersion: 5.4
Contact: Marek Behún <marek.behun@nic.cz>
Description: (R) ECDSA public key (in pubkey hex compressed form) computed
as pair to the ECDSA private key burned into eFuses of this
Turris Mox Board.
Format: string
What: /sys/firmware/turris-mox-rwtm/ram_size
Date: August 2019
KernelVersion: 5.4
Contact: Marek Behún <marek.behun@nic.cz>
Description: (R) RAM size in MiB of this Turris Mox board as was detected
during manufacturing and burned into eFuses. Can be 512 or 1024.
Format: %i
What: /sys/firmware/turris-mox-rwtm/serial_number
Date: August 2019
KernelVersion: 5.4
Contact: Marek Behún <marek.behun@nic.cz>
Description: (R) Serial number burned into eFuses of this Turris Mox device.
Format: %016X
......@@ -73,6 +73,16 @@ Required properties:
as used by the firmware. Refer to platform details
for your implementation for the IDs to use.
Reset signal bindings for the reset domains based on SCMI Message Protocol
------------------------------------------------------------
This binding for the SCMI reset domain providers uses the generic reset
signal binding[5].
Required properties:
- #reset-cells : Should be 1. Contains the reset domain ID value used
by SCMI commands.
SRAM and Shared Memory for SCMI
-------------------------------
......@@ -93,6 +103,7 @@ Required sub-node properties:
[2] Documentation/devicetree/bindings/power/power_domain.txt
[3] Documentation/devicetree/bindings/thermal/thermal.txt
[4] Documentation/devicetree/bindings/sram/sram.txt
[5] Documentation/devicetree/bindings/reset/reset.txt
Example:
......@@ -152,6 +163,11 @@ firmware {
reg = <0x15>;
#thermal-sensor-cells = <1>;
};
scmi_reset: protocol@16 {
reg = <0x16>;
#reset-cells = <1>;
};
};
};
......@@ -166,6 +182,7 @@ hdlcd@7ff60000 {
reg = <0 0x7ff60000 0 0x1000>;
clocks = <&scmi_clk 4>;
power-domains = <&scmi_devpd 1>;
resets = <&scmi_reset 10>;
};
thermal-zones {
......
Turris Mox module status and configuration bus (over SPI)
Required properties:
- compatible : Should be "cznic,moxtet"
- #address-cells : Has to be 1
- #size-cells : Has to be 0
- spi-cpol : Required inverted clock polarity
- spi-cpha : Required shifted clock phase
- interrupts : Must contain reference to the shared interrupt line
- interrupt-controller : Required
- #interrupt-cells : Has to be 1
For other required and optional properties of SPI slave nodes please refer to
../spi/spi-bus.txt.
Required properties of subnodes:
- reg : Should be position on the Moxtet bus (how many Moxtet
modules are between this module and CPU module, so
either 0 or a positive integer)
The driver finds the devices connected to the bus by itself, but it may be
needed to reference some of them from other parts of the device tree. In that
case the devices can be defined as subnodes of the moxtet node.
Example:
moxtet@1 {
compatible = "cznic,moxtet";
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
spi-max-frequency = <10000000>;
spi-cpol;
spi-cpha;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&gpiosb>;
interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
moxtet_sfp: gpio@0 {
compatible = "cznic,moxtet-gpio";
gpio-controller;
#gpio-cells = <2>;
reg = <0>;
}
};
Turris Mox rWTM firmware driver
Required properties:
- compatible : Should be "cznic,turris-mox-rwtm"
- mboxes : Must contain a reference to associated mailbox
This device tree node should be used on Turris Mox, or potentially another A3700
compatible device running the Mox's rWTM firmware in the secure processor (for
example it is possible to flash this firmware into EspressoBin).
Example:
firmware {
turris-mox-rwtm {
compatible = "cznic,turris-mox-rwtm";
mboxes = <&rwtm 0>;
status = "okay";
};
};
......@@ -9,14 +9,16 @@ Required properties:
- compatible: must contain one of the following:
* "qcom,scm-apq8064"
* "qcom,scm-apq8084"
* "qcom,scm-ipq4019"
* "qcom,scm-msm8660"
* "qcom,scm-msm8916"
* "qcom,scm-msm8960"
* "qcom,scm-msm8974"
* "qcom,scm-msm8996"
* "qcom,scm-msm8998"
* "qcom,scm-ipq4019"
* "qcom,scm-sc7180"
* "qcom,scm-sdm845"
* "qcom,scm-sm8150"
and:
* "qcom,scm"
- clocks: Specifies clocks needed by the SCM interface, if any:
......
Turris Mox Moxtet GPIO expander via Moxtet bus
Required properties:
- compatible : Should be "cznic,moxtet-gpio".
- gpio-controller : Marks the device node as a GPIO controller.
- #gpio-cells : Should be two. For consumer use see gpio.txt.
Other properties are required for a Moxtet bus device, please refer to
Documentation/devicetree/bindings/bus/moxtet.txt.
Example:
moxtet_sfp: gpio@0 {
compatible = "cznic,moxtet-gpio";
gpio-controller;
#gpio-cells = <2>;
reg = <0>;
}
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2019 BayLibre, SAS
%YAML 1.2
---
$id: "http://devicetree.org/schemas/power/amlogic,meson-ee-pwrc.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Amlogic Meson Everything-Else Power Domains
maintainers:
- Neil Armstrong <narmstrong@baylibre.com>
description: |+
The Everything-Else Power Domains node should be the child of a syscon
node with the required property:
- compatible: Should be the following:
"amlogic,meson-gx-hhi-sysctrl", "simple-mfd", "syscon"
Refer to the the bindings described in
Documentation/devicetree/bindings/mfd/syscon.txt
properties:
compatible:
enum:
- amlogic,meson-g12a-pwrc
- amlogic,meson-sm1-pwrc
clocks:
minItems: 2
clock-names:
items:
- const: vpu
- const: vapb
resets:
minItems: 11
reset-names:
items:
- const: viu
- const: venc
- const: vcbus
- const: bt656
- const: rdma
- const: venci
- const: vencp
- const: vdac
- const: vdi6
- const: vencl
- const: vid_lock
"#power-domain-cells":
const: 1
amlogic,ao-sysctrl:
description: phandle to the AO sysctrl node
allOf:
- $ref: /schemas/types.yaml#/definitions/phandle
required:
- compatible
- clocks
- clock-names
- resets
- reset-names
- "#power-domain-cells"
- amlogic,ao-sysctrl
examples:
- |
pwrc: power-controller {
compatible = "amlogic,meson-sm1-pwrc";
#power-domain-cells = <1>;
amlogic,ao-sysctrl = <&rti>;
resets = <&reset_viu>,
<&reset_venc>,
<&reset_vcbus>,
<&reset_bt656>,
<&reset_rdma>,
<&reset_venci>,
<&reset_vencp>,
<&reset_vdac>,
<&reset_vdi6>,
<&reset_vencl>,
<&reset_vid_lock>;
reset-names = "viu", "venc", "vcbus", "bt656",
"rdma", "venci", "vencp", "vdac",
"vdi6", "vencl", "vid_lock";
clocks = <&clk_vpu>, <&clk_vapb>;
clock-names = "vpu", "vapb";
};
......@@ -8,6 +8,7 @@ Required properties:
- compatible:
- For i.MX7 SoCs should be "fsl,imx7d-src", "syscon"
- For i.MX8MQ SoCs should be "fsl,imx8mq-src", "syscon"
- For i.MX8MM SoCs should be "fsl,imx8mm-src", "fsl,imx8mq-src", "syscon"
- reg: should be register base and length as documented in the
datasheet
- interrupts: Should contain SRC interrupt
......@@ -46,5 +47,6 @@ Example:
For list of all valid reset indices see
<dt-bindings/reset/imx7-reset.h> for i.MX7 and
<dt-bindings/reset/imx8mq-reset.h> for i.MX8MQ
<dt-bindings/reset/imx7-reset.h> for i.MX7,
<dt-bindings/reset/imx8mq-reset.h> for i.MX8MQ and
<dt-bindings/reset/imx8mq-reset.h> for i.MX8MM
Synopsys DesignWare Reset controller
=======================================
Please also refer to reset.txt in this directory for common reset
controller binding usage.
Required properties:
- compatible: should be one of the following.
"snps,dw-high-reset" - for active high configuration
"snps,dw-low-reset" - for active low configuration
- reg: physical base address of the controller and length of memory mapped
region.
- #reset-cells: must be 1.
example:
dw_rst_1: reset-controller@0000 {
compatible = "snps,dw-high-reset";
reg = <0x0000 0x4>;
#reset-cells = <1>;
};
dw_rst_2: reset-controller@1000 {i
compatible = "snps,dw-low-reset";
reg = <0x1000 0x8>;
#reset-cells = <1>;
};
......@@ -11,6 +11,7 @@ Required properties:
"amlogic,meson8b-clk-measure" for Meson8b SoCs
"amlogic,meson-axg-clk-measure" for AXG SoCs
"amlogic,meson-g12a-clk-measure" for G12a SoCs
"amlogic,meson-sm1-clk-measure" for SM1 SoCs
- reg: base address and size of the Clock Measurer register space.
Example:
......
......@@ -18,7 +18,8 @@ Required properties:
- reg : offset and length of the device registers.
- bus-frequency : the clock frequency for QUICC Engine.
- fsl,qe-num-riscs: define how many RISC engines the QE has.
- fsl,qe-num-snums: define how many serial number(SNUM) the QE can use for the
- fsl,qe-snums: This property has to be specified as '/bits/ 8' value,
defining the array of serial number (SNUM) values for the virtual
threads.
Optional properties:
......@@ -34,6 +35,11 @@ Recommended properties
- brg-frequency : the internal clock source frequency for baud-rate
generators in Hz.
Deprecated properties
- fsl,qe-num-snums: define how many serial number(SNUM) the QE can use
for the threads. Use fsl,qe-snums instead to not only specify the
number of snums, but also their values.
Example:
qe@e0100000 {
#address-cells = <1>;
......@@ -44,6 +50,11 @@ Example:
reg = <e0100000 480>;
brg-frequency = <0>;
bus-frequency = <179A7B00>;
fsl,qe-snums = /bits/ 8 <
0x04 0x05 0x0C 0x0D 0x14 0x15 0x1C 0x1D
0x24 0x25 0x2C 0x2D 0x34 0x35 0x88 0x89
0x98 0x99 0xA8 0xA9 0xB8 0xB9 0xC8 0xC9
0xD8 0xD9 0xE8 0xE9>;
}
* Multi-User RAM (MURAM)
......
......@@ -15,7 +15,10 @@ power-domains.
- compatible:
Usage: required
Value type: <string>
Definition: must be "qcom,sdm845-aoss-qmp"
Definition: must be one of:
"qcom,sc7180-aoss-qmp"
"qcom,sdm845-aoss-qmp"
"qcom,sm8150-aoss-qmp"
- reg:
Usage: required
......
......@@ -19,8 +19,15 @@ child of the pmmc node.
Required Properties:
--------------------
- compatible: should be "ti,sci-pm-domain"
- #power-domain-cells: Must be 1 so that an id can be provided in each
device node.
- #power-domain-cells: Can be one of the following:
1: Containing the device id of each node
2: First entry should be device id
Second entry should be one of the floowing:
TI_SCI_PD_EXCLUSIVE: To allow device to be
exclusively controlled by
the requesting hosts.
TI_SCI_PD_SHARED: To allow device to be shared
by multiple hosts.
Example (K2G):
-------------
......
......@@ -1617,6 +1617,21 @@ F: drivers/clocksource/timer-atlas7.c
N: [^a-z]sirf
X: drivers/gnss
ARM/CZ.NIC TURRIS MOX SUPPORT
M: Marek Behun <marek.behun@nic.cz>
W: http://mox.turris.cz
S: Maintained
F: Documentation/ABI/testing/debugfs-moxtet
F: Documentation/ABI/testing/sysfs-bus-moxtet-devices
F: Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm
F: Documentation/devicetree/bindings/bus/moxtet.txt
F: Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt
F: Documentation/devicetree/bindings/gpio/gpio-moxtet.txt
F: include/linux/moxtet.h
F: drivers/bus/moxtet.c
F: drivers/firmware/turris-mox-rwtm.c
F: drivers/gpio/gpio-moxtet.c
ARM/EBSA110 MACHINE SUPPORT
M: Russell King <linux@armlinux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
......@@ -15530,6 +15545,7 @@ F: drivers/clk/clk-sc[mp]i.c
F: drivers/cpufreq/sc[mp]i-cpufreq.c
F: drivers/firmware/arm_scpi.c
F: drivers/firmware/arm_scmi/
F: drivers/reset/reset-scmi.c
F: include/linux/sc[mp]i_protocol.h
SYSTEM RESET/SHUTDOWN DRIVERS
......@@ -15838,6 +15854,7 @@ F: drivers/firmware/ti_sci*
F: include/linux/soc/ti/ti_sci_protocol.h
F: Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
F: drivers/soc/ti/ti_sci_pm_domains.c
F: include/dt-bindings/soc/ti,sci_pm_domain.h
F: Documentation/devicetree/bindings/reset/ti,sci-reset.txt
F: Documentation/devicetree/bindings/clock/ti,sci-clk.txt
F: drivers/clk/keystone/sci-clk.c
......
......@@ -8,7 +8,7 @@
*/
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
......
......@@ -36,6 +36,7 @@
#include <linux/platform_data/ti-aemif.h>
#include <linux/platform_data/spi-davinci.h>
#include <linux/platform_data/uio_pruss.h>
#include <linux/property.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/tps6507x.h>
#include <linux/regulator/fixed.h>
......@@ -802,37 +803,79 @@ static const short da850_evm_mmcsd0_pins[] __initconst = {
-1
};
static void da850_panel_power_ctrl(int val)
{
/* lcd backlight */
gpio_set_value(DA850_LCD_BL_PIN, val);
static struct property_entry da850_lcd_backlight_props[] = {
PROPERTY_ENTRY_BOOL("default-on"),
{ }
};
/* lcd power */
gpio_set_value(DA850_LCD_PWR_PIN, val);
}
static struct gpiod_lookup_table da850_lcd_backlight_gpio_table = {
.dev_id = "gpio-backlight",
.table = {
GPIO_LOOKUP("davinci_gpio", DA850_LCD_BL_PIN, NULL, 0),
{ }
},
};
static const struct platform_device_info da850_lcd_backlight_info = {
.name = "gpio-backlight",
.id = PLATFORM_DEVID_NONE,
.properties = da850_lcd_backlight_props,
};
static struct regulator_consumer_supply da850_lcd_supplies[] = {
REGULATOR_SUPPLY("lcd", NULL),
};
static struct regulator_init_data da850_lcd_supply_data = {
.consumer_supplies = da850_lcd_supplies,
.num_consumer_supplies = ARRAY_SIZE(da850_lcd_supplies),
.constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
};
static struct fixed_voltage_config da850_lcd_supply = {
.supply_name = "lcd",
.microvolts = 33000000,
.init_data = &da850_lcd_supply_data,
};
static struct platform_device da850_lcd_supply_device = {
.name = "reg-fixed-voltage",
.id = 1, /* Dummy fixed regulator is 0 */
.dev = {
.platform_data = &da850_lcd_supply,
},
};
static struct gpiod_lookup_table da850_lcd_supply_gpio_table = {
.dev_id = "reg-fixed-voltage.1",
.table = {
GPIO_LOOKUP("davinci_gpio", DA850_LCD_PWR_PIN, NULL, 0),
{ }
},
};
static struct gpiod_lookup_table *da850_lcd_gpio_lookups[] = {
&da850_lcd_backlight_gpio_table,
&da850_lcd_supply_gpio_table,
};
static int da850_lcd_hw_init(void)
{
struct platform_device *backlight;
int status;
status = gpio_request(DA850_LCD_BL_PIN, "lcd bl");
if (status < 0)
return status;
status = gpio_request(DA850_LCD_PWR_PIN, "lcd pwr");
if (status < 0) {
gpio_free(DA850_LCD_BL_PIN);
return status;
}
gpiod_add_lookup_tables(da850_lcd_gpio_lookups,
ARRAY_SIZE(da850_lcd_gpio_lookups));
gpio_direction_output(DA850_LCD_BL_PIN, 0);
gpio_direction_output(DA850_LCD_PWR_PIN, 0);
backlight = platform_device_register_full(&da850_lcd_backlight_info);
if (IS_ERR(backlight))
return PTR_ERR(backlight);
/* Switch off panel power and backlight */
da850_panel_power_ctrl(0);
/* Switch on panel power and backlight */
da850_panel_power_ctrl(1);
status = platform_device_register(&da850_lcd_supply_device);
if (status)
return status;
return 0;
}
......@@ -1443,7 +1486,6 @@ static __init void da850_evm_init(void)
if (ret)
pr_warn("%s: LCD initialization failed: %d\n", __func__, ret);
sharp_lk043t1dg01_pdata.panel_power_ctrl = da850_panel_power_ctrl,
ret = da8xx_register_lcdc(&sharp_lk043t1dg01_pdata);
if (ret)
pr_warn("%s: LCDC registration failed: %d\n", __func__, ret);
......
......@@ -33,6 +33,7 @@ static struct bus_type soc_bus_type = {
static DEVICE_ATTR(machine, S_IRUGO, soc_info_get, NULL);
static DEVICE_ATTR(family, S_IRUGO, soc_info_get, NULL);
static DEVICE_ATTR(serial_number, S_IRUGO, soc_info_get, NULL);
static DEVICE_ATTR(soc_id, S_IRUGO, soc_info_get, NULL);
static DEVICE_ATTR(revision, S_IRUGO, soc_info_get, NULL);
......@@ -57,6 +58,9 @@ static umode_t soc_attribute_mode(struct kobject *kobj,
if ((attr == &dev_attr_revision.attr)
&& (soc_dev->attr->revision != NULL))
return attr->mode;
if ((attr == &dev_attr_serial_number.attr)
&& (soc_dev->attr->serial_number != NULL))
return attr->mode;
if ((attr == &dev_attr_soc_id.attr)
&& (soc_dev->attr->soc_id != NULL))
return attr->mode;
......@@ -77,6 +81,8 @@ static ssize_t soc_info_get(struct device *dev,
return sprintf(buf, "%s\n", soc_dev->attr->family);
if (attr == &dev_attr_revision)
return sprintf(buf, "%s\n", soc_dev->attr->revision);
if (attr == &dev_attr_serial_number)
return sprintf(buf, "%s\n", soc_dev->attr->serial_number);
if (attr == &dev_attr_soc_id)
return sprintf(buf, "%s\n", soc_dev->attr->soc_id);
......@@ -87,6 +93,7 @@ static ssize_t soc_info_get(struct device *dev,
static struct attribute *soc_attr[] = {
&dev_attr_machine.attr,
&dev_attr_family.attr,
&dev_attr_serial_number.attr,
&dev_attr_soc_id.attr,
&dev_attr_revision.attr,
NULL,
......@@ -157,6 +164,7 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
out1:
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(soc_device_register);
/* Ensure soc_dev->attr is freed prior to calling soc_device_unregister. */
void soc_device_unregister(struct soc_device *soc_dev)
......@@ -166,6 +174,7 @@ void soc_device_unregister(struct soc_device *soc_dev)
device_unregister(&soc_dev->dev);
early_soc_dev_attr = NULL;
}
EXPORT_SYMBOL_GPL(soc_device_unregister);
static int __init soc_bus_register(void)
{
......
......@@ -29,6 +29,16 @@ config BRCMSTB_GISB_ARB
arbiter. This driver provides timeout and target abort error handling
and internal bus master decoding.
config MOXTET
tristate "CZ.NIC Turris Mox module configuration bus"
depends on SPI_MASTER && OF
help
Say yes here to add support for the module configuration bus found
on CZ.NIC's Turris Mox. This is needed for the ability to discover
the order in which the modules are connected and to get/set some of
their settings. For example the GPIOs on Mox SFP module are
configured through this bus.
config HISILICON_LPC
bool "Support for ISA I/O space on HiSilicon Hip06/7"
depends on ARM64 && (ARCH_HISI || COMPILE_TEST)
......
......@@ -8,6 +8,7 @@ obj-$(CONFIG_ARM_CCI) += arm-cci.o
obj-$(CONFIG_HISILICON_LPC) += hisi_lpc.o
obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o
obj-$(CONFIG_MOXTET) += moxtet.o
# DPAA2 fsl-mc bus
obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
......
......@@ -330,7 +330,6 @@ void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
fsl_mc_resource_free(resource);
device_link_del(mc_adev->consumer_link);
mc_adev->consumer_link = NULL;
}
EXPORT_SYMBOL_GPL(fsl_mc_object_free);
......
......@@ -255,7 +255,6 @@ void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
fsl_destroy_mc_io(mc_io);
fsl_mc_resource_free(resource);
device_link_del(dpmcp_dev->consumer_link);
dpmcp_dev->consumer_link = NULL;
}
EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
......
......@@ -19,6 +19,8 @@ struct imx_weim_devtype {
unsigned int cs_count;
unsigned int cs_regs_count;
unsigned int cs_stride;
unsigned int wcr_offset;
unsigned int wcr_bcm;
};
static const struct imx_weim_devtype imx1_weim_devtype = {
......@@ -37,6 +39,8 @@ static const struct imx_weim_devtype imx50_weim_devtype = {
.cs_count = 4,
.cs_regs_count = 6,
.cs_stride = 0x18,
.wcr_offset = 0x90,
.wcr_bcm = BIT(0),
};
static const struct imx_weim_devtype imx51_weim_devtype = {
......@@ -72,7 +76,7 @@ static const struct of_device_id weim_id_table[] = {
};
MODULE_DEVICE_TABLE(of, weim_id_table);
static int __init imx_weim_gpr_setup(struct platform_device *pdev)
static int imx_weim_gpr_setup(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct property *prop;
......@@ -122,10 +126,10 @@ static int __init imx_weim_gpr_setup(struct platform_device *pdev)
}
/* Parse and set the timing for this device. */
static int __init weim_timing_setup(struct device *dev,
struct device_node *np, void __iomem *base,
const struct imx_weim_devtype *devtype,
struct cs_timing_state *ts)
static int weim_timing_setup(struct device *dev,
struct device_node *np, void __iomem *base,
const struct imx_weim_devtype *devtype,
struct cs_timing_state *ts)
{
u32 cs_idx, value[MAX_CS_REGS_COUNT];
int i, ret;
......@@ -183,8 +187,7 @@ static int __init weim_timing_setup(struct device *dev,
return 0;
}
static int __init weim_parse_dt(struct platform_device *pdev,
void __iomem *base)
static int weim_parse_dt(struct platform_device *pdev, void __iomem *base)
{
const struct of_device_id *of_id = of_match_device(weim_id_table,
&pdev->dev);
......@@ -192,6 +195,7 @@ static int __init weim_parse_dt(struct platform_device *pdev,
struct device_node *child;
int ret, have_child = 0;
struct cs_timing_state ts = {};
u32 reg;
if (devtype == &imx50_weim_devtype) {
ret = imx_weim_gpr_setup(pdev);
......@@ -199,6 +203,17 @@ static int __init weim_parse_dt(struct platform_device *pdev,
return ret;
}
if (of_property_read_bool(pdev->dev.of_node, "fsl,burst-clk-enable")) {
if (devtype->wcr_bcm) {
reg = readl(base + devtype->wcr_offset);
writel(reg | devtype->wcr_bcm,
base + devtype->wcr_offset);
} else {
dev_err(&pdev->dev, "burst clk mode not supported.\n");
return -EINVAL;
}
}
for_each_available_child_of_node(pdev->dev.of_node, child) {
ret = weim_timing_setup(&pdev->dev, child, base, devtype, &ts);
if (ret)
......@@ -217,7 +232,7 @@ static int __init weim_parse_dt(struct platform_device *pdev,
return ret;
}
static int __init weim_probe(struct platform_device *pdev)
static int weim_probe(struct platform_device *pdev)
{
struct resource *res;
struct clk *clk;
......@@ -254,8 +269,9 @@ static struct platform_driver weim_driver = {
.name = "imx-weim",
.of_match_table = weim_id_table,
},
.probe = weim_probe,
};
module_platform_driver_probe(weim_driver, weim_probe);
module_platform_driver(weim_driver);
MODULE_AUTHOR("Freescale Semiconductor Inc.");
MODULE_DESCRIPTION("i.MX EIM Controller Driver");
......
This diff is collapsed.
......@@ -651,10 +651,8 @@ static int sunxi_rsb_probe(struct platform_device *pdev)
return PTR_ERR(rsb->regs);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "failed to retrieve irq: %d\n", irq);
if (irq < 0)
return irq;
}
rsb->clk = devm_clk_get(dev, NULL);
if (IS_ERR(rsb->clk)) {
......
......@@ -176,7 +176,6 @@ static int uniphier_system_bus_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct uniphier_system_bus_priv *priv;
struct resource *regs;
const __be32 *ranges;
u32 cells, addr, size;
u64 paddr;
......@@ -186,8 +185,7 @@ static int uniphier_system_bus_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->membase = devm_ioremap_resource(dev, regs);
priv->membase = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->membase))
return PTR_ERR(priv->membase);
......
......@@ -69,7 +69,7 @@ static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct scmi_clk *clk = to_scmi_clk(hw);
return clk->handle->clk_ops->rate_set(clk->handle, clk->id, 0, rate);
return clk->handle->clk_ops->rate_set(clk->handle, clk->id, rate);
}
static int scmi_clk_enable(struct clk_hw *hw)
......
......@@ -271,6 +271,20 @@ config TRUSTED_FOUNDATIONS
Choose N if you don't know what this is about.
config TURRIS_MOX_RWTM
tristate "Turris Mox rWTM secure firmware driver"
depends on ARCH_MVEBU || COMPILE_TEST
depends on HAS_DMA && OF
depends on MAILBOX
select HW_RANDOM
select ARMADA_37XX_RWTM_MBOX
help
This driver communicates with the firmware on the Cortex-M3 secure
processor of the Turris Mox router. Enable if you are building for
Turris Mox, and you will be able to read the device serial number and
other manufacturing data and also utilize the Entropy Bit Generator
for hardware random number generation.
config HAVE_ARM_SMCCC
bool
......
......@@ -22,6 +22,7 @@ obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o
CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
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 += psci/
......
......@@ -2,5 +2,5 @@
obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o
scmi-bus-y = bus.o
scmi-driver-y = driver.o
scmi-protocols-y = base.o clock.o perf.o power.o sensors.o
scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o
obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
......@@ -204,7 +204,7 @@ static int scmi_base_discover_agent_get(const struct scmi_handle *handle,
if (ret)
return ret;
*(__le32 *)t->tx.buf = cpu_to_le32(id);
put_unaligned_le32(id, t->tx.buf);
ret = scmi_do_xfer(handle, t);
if (!ret)
......
......@@ -56,7 +56,7 @@ struct scmi_msg_resp_clock_describe_rates {
struct scmi_clock_set_rate {
__le32 flags;
#define CLOCK_SET_ASYNC BIT(0)
#define CLOCK_SET_DELAYED BIT(1)
#define CLOCK_SET_IGNORE_RESP BIT(1)
#define CLOCK_SET_ROUND_UP BIT(2)
#define CLOCK_SET_ROUND_AUTO BIT(3)
__le32 id;
......@@ -67,6 +67,7 @@ struct scmi_clock_set_rate {
struct clock_info {
int num_clocks;
int max_async_req;
atomic_t cur_async_req;
struct scmi_clock_info *clk;
};
......@@ -106,7 +107,7 @@ static int scmi_clock_attributes_get(const struct scmi_handle *handle,
if (ret)
return ret;
*(__le32 *)t->tx.buf = cpu_to_le32(clk_id);
put_unaligned_le32(clk_id, t->tx.buf);
attr = t->rx.buf;
ret = scmi_do_xfer(handle, t);
......@@ -203,39 +204,47 @@ scmi_clock_rate_get(const struct scmi_handle *handle, u32 clk_id, u64 *value)
if (ret)
return ret;
*(__le32 *)t->tx.buf = cpu_to_le32(clk_id);
put_unaligned_le32(clk_id, t->tx.buf);
ret = scmi_do_xfer(handle, t);
if (!ret) {
__le32 *pval = t->rx.buf;
*value = le32_to_cpu(*pval);
*value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
}
if (!ret)
*value = get_unaligned_le64(t->rx.buf);
scmi_xfer_put(handle, t);
return ret;
}
static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id,
u32 config, u64 rate)
u64 rate)
{
int ret;
u32 flags = 0;
struct scmi_xfer *t;
struct scmi_clock_set_rate *cfg;
struct clock_info *ci = handle->clk_priv;
ret = scmi_xfer_get_init(handle, CLOCK_RATE_SET, SCMI_PROTOCOL_CLOCK,
sizeof(*cfg), 0, &t);
if (ret)
return ret;
if (ci->max_async_req &&
atomic_inc_return(&ci->cur_async_req) < ci->max_async_req)
flags |= CLOCK_SET_ASYNC;
cfg = t->tx.buf;
cfg->flags = cpu_to_le32(config);
cfg->flags = cpu_to_le32(flags);
cfg->id = cpu_to_le32(clk_id);
cfg->value_low = cpu_to_le32(rate & 0xffffffff);
cfg->value_high = cpu_to_le32(rate >> 32);
ret = scmi_do_xfer(handle, t);
if (flags & CLOCK_SET_ASYNC)
ret = scmi_do_xfer_with_response(handle, t);
else
ret = scmi_do_xfer(handle, t);
if (ci->max_async_req)
atomic_dec(&ci->cur_async_req);
scmi_xfer_put(handle, t);
return ret;
......
......@@ -15,6 +15,8 @@
#include <linux/scmi_protocol.h>
#include <linux/types.h>
#include <asm/unaligned.h>
#define PROTOCOL_REV_MINOR_MASK GENMASK(15, 0)
#define PROTOCOL_REV_MAJOR_MASK GENMASK(31, 16)
#define PROTOCOL_REV_MAJOR(x) (u16)(FIELD_GET(PROTOCOL_REV_MAJOR_MASK, (x)))
......@@ -48,11 +50,11 @@ struct scmi_msg_resp_prot_version {
/**
* struct scmi_msg_hdr - Message(Tx/Rx) header
*
* @id: The identifier of the command being sent
* @protocol_id: The identifier of the protocol used to send @id command
* @seq: The token to identify the message. when a message/command returns,
* the platform returns the whole message header unmodified including
* the token
* @id: The identifier of the message being sent
* @protocol_id: The identifier of the protocol used to send @id message
* @seq: The token to identify the message. When a message returns, the
* platform returns the whole message header unmodified including the
* token
* @status: Status of the transfer once it's complete
* @poll_completion: Indicate if the transfer needs to be polled for
* completion or interrupt mode is used
......@@ -84,17 +86,21 @@ struct scmi_msg {
* @rx: Receive message, the buffer should be pre-allocated to store
* message. If request-ACK protocol is used, we can reuse the same
* buffer for the rx path as we use for the tx path.
* @done: completion event
* @done: command message transmit completion event
* @async: pointer to delayed response message received event completion
*/
struct scmi_xfer {
struct scmi_msg_hdr hdr;
struct scmi_msg tx;
struct scmi_msg rx;
struct completion done;
struct completion *async_done;
};
void scmi_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer);
int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer);
int scmi_do_xfer_with_response(const struct scmi_handle *h,
struct scmi_xfer *xfer);
int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
size_t tx_size, size_t rx_size, struct scmi_xfer **p);
int scmi_handle_put(const struct scmi_handle *handle);
......
This diff is collapsed.
This diff is collapsed.
......@@ -96,7 +96,7 @@ scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
if (ret)
return ret;
*(__le32 *)t->tx.buf = cpu_to_le32(domain);
put_unaligned_le32(domain, t->tx.buf);
attr = t->rx.buf;
ret = scmi_do_xfer(handle, t);
......@@ -147,11 +147,11 @@ scmi_power_state_get(const struct scmi_handle *handle, u32 domain, u32 *state)
if (ret)
return ret;
*(__le32 *)t->tx.buf = cpu_to_le32(domain);
put_unaligned_le32(domain, t->tx.buf);
ret = scmi_do_xfer(handle, t);
if (!ret)
*state = le32_to_cpu(*(__le32 *)t->rx.buf);
*state = get_unaligned_le32(t->rx.buf);
scmi_xfer_put(handle, t);
return ret;
......
// SPDX-License-Identifier: GPL-2.0
/*
* System Control and Management Interface (SCMI) Reset Protocol
*
* Copyright (C) 2019 ARM Ltd.
*/
#include "common.h"
enum scmi_reset_protocol_cmd {
RESET_DOMAIN_ATTRIBUTES = 0x3,
RESET = 0x4,
RESET_NOTIFY = 0x5,
};
enum scmi_reset_protocol_notify {
RESET_ISSUED = 0x0,
};
#define NUM_RESET_DOMAIN_MASK 0xffff
#define RESET_NOTIFY_ENABLE BIT(0)
struct scmi_msg_resp_reset_domain_attributes {
__le32 attributes;
#define SUPPORTS_ASYNC_RESET(x) ((x) & BIT(31))
#define SUPPORTS_NOTIFY_RESET(x) ((x) & BIT(30))
__le32 latency;
u8 name[SCMI_MAX_STR_SIZE];
};
struct scmi_msg_reset_domain_reset {
__le32 domain_id;
__le32 flags;
#define AUTONOMOUS_RESET BIT(0)
#define EXPLICIT_RESET_ASSERT BIT(1)
#define ASYNCHRONOUS_RESET BIT(2)
__le32 reset_state;
#define ARCH_RESET_TYPE BIT(31)
#define COLD_RESET_STATE BIT(0)
#define ARCH_COLD_RESET (ARCH_RESET_TYPE | COLD_RESET_STATE)
};
struct reset_dom_info {
bool async_reset;
bool reset_notify;
u32 latency_us;
char name[SCMI_MAX_STR_SIZE];
};
struct scmi_reset_info {
int num_domains;
struct reset_dom_info *dom_info;
};
static int scmi_reset_attributes_get(const struct scmi_handle *handle,
struct scmi_reset_info *pi)
{
int ret;
struct scmi_xfer *t;
u32 attr;
ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
SCMI_PROTOCOL_RESET, 0, sizeof(attr), &t);
if (ret)
return ret;
ret = scmi_do_xfer(handle, t);
if (!ret) {
attr = get_unaligned_le32(t->rx.buf);
pi->num_domains = attr & NUM_RESET_DOMAIN_MASK;
}
scmi_xfer_put(handle, t);
return ret;
}
static int
scmi_reset_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
struct reset_dom_info *dom_info)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_resp_reset_domain_attributes *attr;
ret = scmi_xfer_get_init(handle, RESET_DOMAIN_ATTRIBUTES,
SCMI_PROTOCOL_RESET, sizeof(domain),
sizeof(*attr), &t);
if (ret)
return ret;
put_unaligned_le32(domain, t->tx.buf);
attr = t->rx.buf;
ret = scmi_do_xfer(handle, t);
if (!ret) {
u32 attributes = le32_to_cpu(attr->attributes);
dom_info->async_reset = SUPPORTS_ASYNC_RESET(attributes);
dom_info->reset_notify = SUPPORTS_NOTIFY_RESET(attributes);
dom_info->latency_us = le32_to_cpu(attr->latency);
if (dom_info->latency_us == U32_MAX)
dom_info->latency_us = 0;
strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
}
scmi_xfer_put(handle, t);
return ret;
}
static int scmi_reset_num_domains_get(const struct scmi_handle *handle)
{
struct scmi_reset_info *pi = handle->reset_priv;
return pi->num_domains;
}
static char *scmi_reset_name_get(const struct scmi_handle *handle, u32 domain)
{
struct scmi_reset_info *pi = handle->reset_priv;
struct reset_dom_info *dom = pi->dom_info + domain;
return dom->name;
}
static int scmi_reset_latency_get(const struct scmi_handle *handle, u32 domain)
{
struct scmi_reset_info *pi = handle->reset_priv;
struct reset_dom_info *dom = pi->dom_info + domain;
return dom->latency_us;
}
static int scmi_domain_reset(const struct scmi_handle *handle, u32 domain,
u32 flags, u32 state)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_reset_domain_reset *dom;
struct scmi_reset_info *pi = handle->reset_priv;
struct reset_dom_info *rdom = pi->dom_info + domain;
if (rdom->async_reset)
flags |= ASYNCHRONOUS_RESET;
ret = scmi_xfer_get_init(handle, RESET, SCMI_PROTOCOL_RESET,
sizeof(*dom), 0, &t);
if (ret)
return ret;
dom = t->tx.buf;
dom->domain_id = cpu_to_le32(domain);
dom->flags = cpu_to_le32(flags);
dom->domain_id = cpu_to_le32(state);
if (rdom->async_reset)
ret = scmi_do_xfer_with_response(handle, t);
else
ret = scmi_do_xfer(handle, t);
scmi_xfer_put(handle, t);
return ret;
}
static int scmi_reset_domain_reset(const struct scmi_handle *handle, u32 domain)
{
return scmi_domain_reset(handle, domain, AUTONOMOUS_RESET,
ARCH_COLD_RESET);
}
static int
scmi_reset_domain_assert(const struct scmi_handle *handle, u32 domain)
{
return scmi_domain_reset(handle, domain, EXPLICIT_RESET_ASSERT,
ARCH_COLD_RESET);
}
static int
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 = {
.num_domains_get = scmi_reset_num_domains_get,
.name_get = scmi_reset_name_get,
.latency_get = scmi_reset_latency_get,
.reset = scmi_reset_domain_reset,
.assert = scmi_reset_domain_assert,
.deassert = scmi_reset_domain_deassert,
};
static int scmi_reset_protocol_init(struct scmi_handle *handle)
{
int domain;
u32 version;
struct scmi_reset_info *pinfo;
scmi_version_get(handle, SCMI_PROTOCOL_RESET, &version);
dev_dbg(handle->dev, "Reset 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_reset_attributes_get(handle, pinfo);
pinfo->dom_info = devm_kcalloc(handle->dev, pinfo->num_domains,
sizeof(*pinfo->dom_info), GFP_KERNEL);
if (!pinfo->dom_info)
return -ENOMEM;
for (domain = 0; domain < pinfo->num_domains; domain++) {
struct reset_dom_info *dom = pinfo->dom_info + domain;
scmi_reset_domain_attributes_get(handle, domain, dom);
}
handle->reset_ops = &reset_ops;
handle->reset_priv = pinfo;
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);
......@@ -9,8 +9,8 @@
enum scmi_sensor_protocol_cmd {
SENSOR_DESCRIPTION_GET = 0x3,
SENSOR_CONFIG_SET = 0x4,
SENSOR_TRIP_POINT_SET = 0x5,
SENSOR_TRIP_POINT_NOTIFY = 0x4,
SENSOR_TRIP_POINT_CONFIG = 0x5,
SENSOR_READING_GET = 0x6,
};
......@@ -42,9 +42,10 @@ struct scmi_msg_resp_sensor_description {
} desc[0];
};
struct scmi_msg_set_sensor_config {
struct scmi_msg_sensor_trip_point_notify {
__le32 id;
__le32 event_control;
#define SENSOR_TP_NOTIFY_ALL BIT(0)
};
struct scmi_msg_set_sensor_trip_point {
......@@ -119,7 +120,7 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
do {
/* Set the number of sensors to be skipped/already read */
*(__le32 *)t->tx.buf = cpu_to_le32(desc_index);
put_unaligned_le32(desc_index, t->tx.buf);
ret = scmi_do_xfer(handle, t);
if (ret)
......@@ -135,9 +136,10 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
}
for (cnt = 0; cnt < num_returned; cnt++) {
u32 attrh;
u32 attrh, attrl;
struct scmi_sensor_info *s;
attrl = le32_to_cpu(buf->desc[cnt].attributes_low);
attrh = le32_to_cpu(buf->desc[cnt].attributes_high);
s = &si->sensors[desc_index + cnt];
s->id = le32_to_cpu(buf->desc[cnt].id);
......@@ -146,6 +148,8 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
/* Sign extend to a full s8 */
if (s->scale & SENSOR_SCALE_SIGN)
s->scale |= SENSOR_SCALE_EXTEND;
s->async = SUPPORTS_ASYNC_READ(attrl);
s->num_trip_points = NUM_TRIP_POINTS(attrl);
strlcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE);
}
......@@ -160,15 +164,15 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
return ret;
}
static int
scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id)
static int scmi_sensor_trip_point_notify(const struct scmi_handle *handle,
u32 sensor_id, bool enable)
{
int ret;
u32 evt_cntl = BIT(0);
u32 evt_cntl = enable ? SENSOR_TP_NOTIFY_ALL : 0;
struct scmi_xfer *t;
struct scmi_msg_set_sensor_config *cfg;
struct scmi_msg_sensor_trip_point_notify *cfg;
ret = scmi_xfer_get_init(handle, SENSOR_CONFIG_SET,
ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_NOTIFY,
SCMI_PROTOCOL_SENSOR, sizeof(*cfg), 0, &t);
if (ret)
return ret;
......@@ -183,15 +187,16 @@ scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id)
return ret;
}
static int scmi_sensor_trip_point_set(const struct scmi_handle *handle,
u32 sensor_id, u8 trip_id, u64 trip_value)
static int
scmi_sensor_trip_point_config(const struct scmi_handle *handle, u32 sensor_id,
u8 trip_id, u64 trip_value)
{
int ret;
u32 evt_cntl = SENSOR_TP_BOTH;
struct scmi_xfer *t;
struct scmi_msg_set_sensor_trip_point *trip;
ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_SET,
ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_CONFIG,
SCMI_PROTOCOL_SENSOR, sizeof(*trip), 0, &t);
if (ret)
return ret;
......@@ -209,11 +214,13 @@ static int scmi_sensor_trip_point_set(const struct scmi_handle *handle,
}
static int scmi_sensor_reading_get(const struct scmi_handle *handle,
u32 sensor_id, bool async, u64 *value)
u32 sensor_id, u64 *value)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_sensor_reading_get *sensor;
struct sensors_info *si = handle->sensor_priv;
struct scmi_sensor_info *s = si->sensors + sensor_id;
ret = scmi_xfer_get_init(handle, SENSOR_READING_GET,
SCMI_PROTOCOL_SENSOR, sizeof(*sensor),
......@@ -223,14 +230,18 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle,
sensor = t->tx.buf;
sensor->id = cpu_to_le32(sensor_id);
sensor->flags = cpu_to_le32(async ? SENSOR_READ_ASYNC : 0);
ret = scmi_do_xfer(handle, t);
if (!ret) {
__le32 *pval = t->rx.buf;
*value = le32_to_cpu(*pval);
*value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
if (s->async) {
sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC);
ret = scmi_do_xfer_with_response(handle, t);
if (!ret)
*value = get_unaligned_le64((void *)
((__le32 *)t->rx.buf + 1));
} else {
sensor->flags = cpu_to_le32(0);
ret = scmi_do_xfer(handle, t);
if (!ret)
*value = get_unaligned_le64(t->rx.buf);
}
scmi_xfer_put(handle, t);
......@@ -255,8 +266,8 @@ static int scmi_sensor_count_get(const struct scmi_handle *handle)
static struct scmi_sensor_ops sensor_ops = {
.count_get = scmi_sensor_count_get,
.info_get = scmi_sensor_info_get,
.configuration_set = scmi_sensor_configuration_set,
.trip_point_set = scmi_sensor_trip_point_set,
.trip_point_notify = scmi_sensor_trip_point_notify,
.trip_point_config = scmi_sensor_trip_point_config,
.reading_get = scmi_sensor_reading_get,
};
......
# SPDX-License-Identifier: GPL-2.0-only
config IMX_DSP
bool "IMX DSP Protocol driver"
depends on IMX_MBOX
help
This enables DSP IPC protocol between host AP (Linux)
and the firmware running on DSP.
DSP exists on some i.MX8 processors (e.g i.MX8QM, i.MX8QXP).
It acts like a doorbell. Client might use shared memory to
exchange information with DSP side.
config IMX_SCU
bool "IMX SCU Protocol driver"
depends on IMX_MBOX
......
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_IMX_DSP) += imx-dsp.o
obj-$(CONFIG_IMX_SCU) += imx-scu.o misc.o imx-scu-irq.o
obj-$(CONFIG_IMX_SCU_PD) += scu-pd.o
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2019 NXP
* Author: Daniel Baluta <daniel.baluta@nxp.com>
*
* Implementation of the DSP IPC interface (host side)
*/
#include <linux/firmware/imx/dsp.h>
#include <linux/kernel.h>
#include <linux/mailbox_client.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
/*
* imx_dsp_ring_doorbell - triggers an interrupt on the other side (DSP)
*
* @dsp: DSP IPC handle
* @chan_idx: index of the channel where to trigger the interrupt
*
* Returns non-negative value for success, negative value for error
*/
int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc, unsigned int idx)
{
int ret;
struct imx_dsp_chan *dsp_chan;
if (idx >= DSP_MU_CHAN_NUM)
return -EINVAL;
dsp_chan = &ipc->chans[idx];
ret = mbox_send_message(dsp_chan->ch, NULL);
if (ret < 0)
return ret;
return 0;
}
EXPORT_SYMBOL(imx_dsp_ring_doorbell);
/*
* imx_dsp_handle_rx - rx callback used by imx mailbox
*
* @c: mbox client
* @msg: message received
*
* Users of DSP IPC will need to privde handle_reply and handle_request
* callbacks.
*/
static void imx_dsp_handle_rx(struct mbox_client *c, void *msg)
{
struct imx_dsp_chan *chan = container_of(c, struct imx_dsp_chan, cl);
if (chan->idx == 0) {
chan->ipc->ops->handle_reply(chan->ipc);
} else {
chan->ipc->ops->handle_request(chan->ipc);
imx_dsp_ring_doorbell(chan->ipc, 1);
}
}
static int imx_dsp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct imx_dsp_ipc *dsp_ipc;
struct imx_dsp_chan *dsp_chan;
struct mbox_client *cl;
char *chan_name;
int ret;
int i, j;
device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
dsp_ipc = devm_kzalloc(dev, sizeof(*dsp_ipc), GFP_KERNEL);
if (!dsp_ipc)
return -ENOMEM;
for (i = 0; i < DSP_MU_CHAN_NUM; i++) {
if (i < 2)
chan_name = kasprintf(GFP_KERNEL, "txdb%d", i);
else
chan_name = kasprintf(GFP_KERNEL, "rxdb%d", i - 2);
if (!chan_name)
return -ENOMEM;
dsp_chan = &dsp_ipc->chans[i];
cl = &dsp_chan->cl;
cl->dev = dev;
cl->tx_block = false;
cl->knows_txdone = true;
cl->rx_callback = imx_dsp_handle_rx;
dsp_chan->ipc = dsp_ipc;
dsp_chan->idx = i % 2;
dsp_chan->ch = mbox_request_channel_byname(cl, chan_name);
if (IS_ERR(dsp_chan->ch)) {
ret = PTR_ERR(dsp_chan->ch);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to request mbox chan %s ret %d\n",
chan_name, ret);
goto out;
}
dev_dbg(dev, "request mbox chan %s\n", chan_name);
/* chan_name is not used anymore by framework */
kfree(chan_name);
}
dsp_ipc->dev = dev;
dev_set_drvdata(dev, dsp_ipc);
dev_info(dev, "NXP i.MX DSP IPC initialized\n");
return devm_of_platform_populate(dev);
out:
kfree(chan_name);
for (j = 0; j < i; j++) {
dsp_chan = &dsp_ipc->chans[j];
mbox_free_channel(dsp_chan->ch);
}
return ret;
}
static int imx_dsp_remove(struct platform_device *pdev)
{
struct imx_dsp_chan *dsp_chan;
struct imx_dsp_ipc *dsp_ipc;
int i;
dsp_ipc = dev_get_drvdata(&pdev->dev);
for (i = 0; i < DSP_MU_CHAN_NUM; i++) {
dsp_chan = &dsp_ipc->chans[i];
mbox_free_channel(dsp_chan->ch);
}
return 0;
}
static struct platform_driver imx_dsp_driver = {
.driver = {
.name = "imx-dsp",
},
.probe = imx_dsp_probe,
.remove = imx_dsp_remove,
};
builtin_platform_driver(imx_dsp_driver);
MODULE_AUTHOR("Daniel Baluta <daniel.baluta@nxp.com>");
MODULE_DESCRIPTION("IMX DSP IPC protocol driver");
MODULE_LICENSE("GPL v2");
......@@ -92,7 +92,8 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
{ "gpt", IMX_SC_R_GPT_0, 5, true, 0 },
{ "kpp", IMX_SC_R_KPP, 1, false, 0 },
{ "fspi", IMX_SC_R_FSPI_0, 2, true, 0 },
{ "mu", IMX_SC_R_MU_0A, 14, true, 0 },
{ "mu_a", IMX_SC_R_MU_0A, 14, true, 0 },
{ "mu_b", IMX_SC_R_MU_13B, 1, true, 13 },
/* CONN SS */
{ "usb", IMX_SC_R_USB_0, 2, true, 0 },
......@@ -130,6 +131,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
{ "lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, true, 0 },
{ "lpuart", IMX_SC_R_UART_0, 4, true, 0 },
{ "lpspi", IMX_SC_R_SPI_0, 4, true, 0 },
{ "irqstr_dsp", IMX_SC_R_IRQSTR_DSP, 1, false, 0 },
/* VPU SS */
{ "vpu", IMX_SC_R_VPU, 1, false, 0 },
......
......@@ -9,6 +9,7 @@
#include <linux/init.h>
#include <linux/cpumask.h>
#include <linux/export.h>
#include <linux/dma-direct.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/types.h>
......@@ -425,21 +426,23 @@ EXPORT_SYMBOL(qcom_scm_set_remote_state);
* @mem_sz: size of the region.
* @srcvm: vmid for current set of owners, each set bit in
* flag indicate a unique owner
* @newvm: array having new owners and corrsponding permission
* @newvm: array having new owners and corresponding permission
* flags
* @dest_cnt: number of owners in next set.
*
* Return negative errno on failure, 0 on success, with @srcvm updated.
* Return negative errno on failure or 0 on success with @srcvm updated.
*/
int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
unsigned int *srcvm,
struct qcom_scm_vmperm *newvm, int dest_cnt)
const struct qcom_scm_vmperm *newvm,
unsigned int dest_cnt)
{
struct qcom_scm_current_perm_info *destvm;
struct qcom_scm_mem_map_info *mem_to_map;
phys_addr_t mem_to_map_phys;
phys_addr_t dest_phys;
phys_addr_t ptr_phys;
dma_addr_t ptr_dma;
size_t mem_to_map_sz;
size_t dest_sz;
size_t src_sz;
......@@ -447,52 +450,50 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
int next_vm;
__le32 *src;
void *ptr;
int ret;
int len;
int i;
int ret, i, b;
unsigned long srcvm_bits = *srcvm;
src_sz = hweight_long(*srcvm) * sizeof(*src);
src_sz = hweight_long(srcvm_bits) * sizeof(*src);
mem_to_map_sz = sizeof(*mem_to_map);
dest_sz = dest_cnt * sizeof(*destvm);
ptr_sz = ALIGN(src_sz, SZ_64) + ALIGN(mem_to_map_sz, SZ_64) +
ALIGN(dest_sz, SZ_64);
ptr = dma_alloc_coherent(__scm->dev, ptr_sz, &ptr_phys, GFP_KERNEL);
ptr = dma_alloc_coherent(__scm->dev, ptr_sz, &ptr_dma, GFP_KERNEL);
if (!ptr)
return -ENOMEM;
ptr_phys = dma_to_phys(__scm->dev, ptr_dma);
/* Fill source vmid detail */
src = ptr;
len = hweight_long(*srcvm);
for (i = 0; i < len; i++) {
src[i] = cpu_to_le32(ffs(*srcvm) - 1);
*srcvm ^= 1 << (ffs(*srcvm) - 1);
}
i = 0;
for_each_set_bit(b, &srcvm_bits, BITS_PER_LONG)
src[i++] = cpu_to_le32(b);
/* Fill details of mem buff to map */
mem_to_map = ptr + ALIGN(src_sz, SZ_64);
mem_to_map_phys = ptr_phys + ALIGN(src_sz, SZ_64);
mem_to_map[0].mem_addr = cpu_to_le64(mem_addr);
mem_to_map[0].mem_size = cpu_to_le64(mem_sz);
mem_to_map->mem_addr = cpu_to_le64(mem_addr);
mem_to_map->mem_size = cpu_to_le64(mem_sz);
next_vm = 0;
/* Fill details of next vmid detail */
destvm = ptr + ALIGN(mem_to_map_sz, SZ_64) + ALIGN(src_sz, SZ_64);
dest_phys = ptr_phys + ALIGN(mem_to_map_sz, SZ_64) + ALIGN(src_sz, SZ_64);
for (i = 0; i < dest_cnt; i++) {
destvm[i].vmid = cpu_to_le32(newvm[i].vmid);
destvm[i].perm = cpu_to_le32(newvm[i].perm);
destvm[i].ctx = 0;
destvm[i].ctx_size = 0;
next_vm |= BIT(newvm[i].vmid);
for (i = 0; i < dest_cnt; i++, destvm++, newvm++) {
destvm->vmid = cpu_to_le32(newvm->vmid);
destvm->perm = cpu_to_le32(newvm->perm);
destvm->ctx = 0;
destvm->ctx_size = 0;
next_vm |= BIT(newvm->vmid);
}
ret = __qcom_scm_assign_mem(__scm->dev, mem_to_map_phys, mem_to_map_sz,
ptr_phys, src_sz, dest_phys, dest_sz);
dma_free_coherent(__scm->dev, ALIGN(ptr_sz, SZ_64), ptr, ptr_phys);
dma_free_coherent(__scm->dev, ptr_sz, ptr, ptr_dma);
if (ret) {
dev_err(__scm->dev,
"Assign memory protection call failed %d.\n", ret);
"Assign memory protection call failed %d\n", ret);
return -EINVAL;
}
......
......@@ -635,6 +635,7 @@ static int ti_sci_get_device_state(const struct ti_sci_handle *handle,
/**
* ti_sci_cmd_get_device() - command to request for device managed by TISCI
* that can be shared with other hosts.
* @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
* @id: Device Identifier
*
......@@ -642,11 +643,29 @@ static int ti_sci_get_device_state(const struct ti_sci_handle *handle,
* usage count by balancing get_device with put_device. No refcounting is
* managed by driver for that purpose.
*
* NOTE: The request is for exclusive access for the processor.
*
* Return: 0 if all went fine, else return appropriate error.
*/
static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
{
return ti_sci_set_device_state(handle, id, 0,
MSG_DEVICE_SW_STATE_ON);
}
/**
* ti_sci_cmd_get_device_exclusive() - command to request for device managed by
* TISCI that is exclusively owned by the
* requesting host.
* @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
* @id: Device Identifier
*
* Request for the device - NOTE: the client MUST maintain integrity of
* usage count by balancing get_device with put_device. No refcounting is
* managed by driver for that purpose.
*
* Return: 0 if all went fine, else return appropriate error.
*/
static int ti_sci_cmd_get_device_exclusive(const struct ti_sci_handle *handle,
u32 id)
{
return ti_sci_set_device_state(handle, id,
MSG_FLAG_DEVICE_EXCLUSIVE,
......@@ -665,6 +684,26 @@ static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
* Return: 0 if all went fine, else return appropriate error.
*/
static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id)
{
return ti_sci_set_device_state(handle, id, 0,
MSG_DEVICE_SW_STATE_RETENTION);
}
/**
* ti_sci_cmd_idle_device_exclusive() - Command to idle a device managed by
* TISCI that is exclusively owned by
* requesting host.
* @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
* @id: Device Identifier
*
* Request for the device - NOTE: the client MUST maintain integrity of
* usage count by balancing get_device with put_device. No refcounting is
* managed by driver for that purpose.
*
* Return: 0 if all went fine, else return appropriate error.
*/
static int ti_sci_cmd_idle_device_exclusive(const struct ti_sci_handle *handle,
u32 id)
{
return ti_sci_set_device_state(handle, id,
MSG_FLAG_DEVICE_EXCLUSIVE,
......@@ -2894,7 +2933,9 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
core_ops->reboot_device = ti_sci_cmd_core_reboot;
dops->get_device = ti_sci_cmd_get_device;
dops->get_device_exclusive = ti_sci_cmd_get_device_exclusive;
dops->idle_device = ti_sci_cmd_idle_device;
dops->idle_device_exclusive = ti_sci_cmd_idle_device_exclusive;
dops->put_device = ti_sci_cmd_put_device;
dops->is_valid = ti_sci_cmd_dev_is_valid;
......
// SPDX-License-Identifier: GPL-2.0
/*
* Turris Mox rWTM firmware driver
*
* Copyright (C) 2019 Marek Behun <marek.behun@nic.cz>
*/
#include <linux/armada-37xx-rwtm-mailbox.h>
#include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/hw_random.h>
#include <linux/mailbox_client.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#define DRIVER_NAME "turris-mox-rwtm"
/*
* The macros and constants below come from Turris Mox's rWTM firmware code.
* This firmware is open source and it's sources can be found at
* https://gitlab.labs.nic.cz/turris/mox-boot-builder/tree/master/wtmi.
*/
#define MBOX_STS_SUCCESS (0 << 30)
#define MBOX_STS_FAIL (1 << 30)
#define MBOX_STS_BADCMD (2 << 30)
#define MBOX_STS_ERROR(s) ((s) & (3 << 30))
#define MBOX_STS_VALUE(s) (((s) >> 10) & 0xfffff)
#define MBOX_STS_CMD(s) ((s) & 0x3ff)
enum mbox_cmd {
MBOX_CMD_GET_RANDOM = 1,
MBOX_CMD_BOARD_INFO = 2,
MBOX_CMD_ECDSA_PUB_KEY = 3,
MBOX_CMD_HASH = 4,
MBOX_CMD_SIGN = 5,
MBOX_CMD_VERIFY = 6,
MBOX_CMD_OTP_READ = 7,
MBOX_CMD_OTP_WRITE = 8,
};
struct mox_kobject;
struct mox_rwtm {
struct device *dev;
struct mbox_client mbox_client;
struct mbox_chan *mbox;
struct mox_kobject *kobj;
struct hwrng hwrng;
struct armada_37xx_rwtm_rx_msg reply;
void *buf;
dma_addr_t buf_phys;
struct mutex busy;
struct completion cmd_done;
/* board information */
int has_board_info;
u64 serial_number;
int board_version, ram_size;
u8 mac_address1[6], mac_address2[6];
/* public key burned in eFuse */
int has_pubkey;
u8 pubkey[135];
};
struct mox_kobject {
struct kobject kobj;
struct mox_rwtm *rwtm;
};
static inline struct kobject *rwtm_to_kobj(struct mox_rwtm *rwtm)
{
return &rwtm->kobj->kobj;
}
static inline struct mox_rwtm *to_rwtm(struct kobject *kobj)
{
return container_of(kobj, struct mox_kobject, kobj)->rwtm;
}
static void mox_kobj_release(struct kobject *kobj)
{
kfree(to_rwtm(kobj)->kobj);
}
static struct kobj_type mox_kobj_ktype = {
.release = mox_kobj_release,
.sysfs_ops = &kobj_sysfs_ops,
};
static int mox_kobj_create(struct mox_rwtm *rwtm)
{
rwtm->kobj = kzalloc(sizeof(*rwtm->kobj), GFP_KERNEL);
if (!rwtm->kobj)
return -ENOMEM;
kobject_init(rwtm_to_kobj(rwtm), &mox_kobj_ktype);
if (kobject_add(rwtm_to_kobj(rwtm), firmware_kobj, "turris-mox-rwtm")) {
kobject_put(rwtm_to_kobj(rwtm));
return -ENXIO;
}
rwtm->kobj->rwtm = rwtm;
return 0;
}
#define MOX_ATTR_RO(name, format, cat) \
static ssize_t \
name##_show(struct kobject *kobj, struct kobj_attribute *a, \
char *buf) \
{ \
struct mox_rwtm *rwtm = to_rwtm(kobj); \
if (!rwtm->has_##cat) \
return -ENODATA; \
return sprintf(buf, format, rwtm->name); \
} \
static struct kobj_attribute mox_attr_##name = __ATTR_RO(name)
MOX_ATTR_RO(serial_number, "%016llX\n", board_info);
MOX_ATTR_RO(board_version, "%i\n", board_info);
MOX_ATTR_RO(ram_size, "%i\n", board_info);
MOX_ATTR_RO(mac_address1, "%pM\n", board_info);
MOX_ATTR_RO(mac_address2, "%pM\n", board_info);
MOX_ATTR_RO(pubkey, "%s\n", pubkey);
static int mox_get_status(enum mbox_cmd cmd, u32 retval)
{
if (MBOX_STS_CMD(retval) != cmd ||
MBOX_STS_ERROR(retval) != MBOX_STS_SUCCESS)
return -EIO;
else if (MBOX_STS_ERROR(retval) == MBOX_STS_FAIL)
return -(int)MBOX_STS_VALUE(retval);
else
return MBOX_STS_VALUE(retval);
}
static const struct attribute *mox_rwtm_attrs[] = {
&mox_attr_serial_number.attr,
&mox_attr_board_version.attr,
&mox_attr_ram_size.attr,
&mox_attr_mac_address1.attr,
&mox_attr_mac_address2.attr,
&mox_attr_pubkey.attr,
NULL
};
static void mox_rwtm_rx_callback(struct mbox_client *cl, void *data)
{
struct mox_rwtm *rwtm = dev_get_drvdata(cl->dev);
struct armada_37xx_rwtm_rx_msg *msg = data;
rwtm->reply = *msg;
complete(&rwtm->cmd_done);
}
static void reply_to_mac_addr(u8 *mac, u32 t1, u32 t2)
{
mac[0] = t1 >> 8;
mac[1] = t1;
mac[2] = t2 >> 24;
mac[3] = t2 >> 16;
mac[4] = t2 >> 8;
mac[5] = t2;
}
static int mox_get_board_info(struct mox_rwtm *rwtm)
{
struct armada_37xx_rwtm_tx_msg msg;
struct armada_37xx_rwtm_rx_msg *reply = &rwtm->reply;
int ret;
msg.command = MBOX_CMD_BOARD_INFO;
ret = mbox_send_message(rwtm->mbox, &msg);
if (ret < 0)
return ret;
ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
if (ret < 0)
return ret;
ret = mox_get_status(MBOX_CMD_BOARD_INFO, reply->retval);
if (ret < 0 && ret != -ENODATA) {
return ret;
} else if (ret == -ENODATA) {
dev_warn(rwtm->dev,
"Board does not have manufacturing information burned!\n");
} else {
rwtm->serial_number = reply->status[1];
rwtm->serial_number <<= 32;
rwtm->serial_number |= reply->status[0];
rwtm->board_version = reply->status[2];
rwtm->ram_size = reply->status[3];
reply_to_mac_addr(rwtm->mac_address1, reply->status[4],
reply->status[5]);
reply_to_mac_addr(rwtm->mac_address2, reply->status[6],
reply->status[7]);
rwtm->has_board_info = 1;
pr_info("Turris Mox serial number %016llX\n",
rwtm->serial_number);
pr_info(" board version %i\n", rwtm->board_version);
pr_info(" burned RAM size %i MiB\n", rwtm->ram_size);
}
msg.command = MBOX_CMD_ECDSA_PUB_KEY;
ret = mbox_send_message(rwtm->mbox, &msg);
if (ret < 0)
return ret;
ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
if (ret < 0)
return ret;
ret = mox_get_status(MBOX_CMD_ECDSA_PUB_KEY, reply->retval);
if (ret < 0 && ret != -ENODATA) {
return ret;
} else if (ret == -ENODATA) {
dev_warn(rwtm->dev, "Board has no public key burned!\n");
} else {
u32 *s = reply->status;
rwtm->has_pubkey = 1;
sprintf(rwtm->pubkey,
"%06x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
ret, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7],
s[8], s[9], s[10], s[11], s[12], s[13], s[14], s[15]);
}
return 0;
}
static int mox_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
struct mox_rwtm *rwtm = (struct mox_rwtm *) rng->priv;
struct armada_37xx_rwtm_tx_msg msg;
int ret;
if (max > 4096)
max = 4096;
msg.command = MBOX_CMD_GET_RANDOM;
msg.args[0] = 1;
msg.args[1] = rwtm->buf_phys;
msg.args[2] = (max + 3) & ~3;
if (!wait) {
if (!mutex_trylock(&rwtm->busy))
return -EBUSY;
} else {
mutex_lock(&rwtm->busy);
}
ret = mbox_send_message(rwtm->mbox, &msg);
if (ret < 0)
goto unlock_mutex;
ret = wait_for_completion_interruptible(&rwtm->cmd_done);
if (ret < 0)
goto unlock_mutex;
ret = mox_get_status(MBOX_CMD_GET_RANDOM, rwtm->reply.retval);
if (ret < 0)
goto unlock_mutex;
memcpy(data, rwtm->buf, max);
ret = max;
unlock_mutex:
mutex_unlock(&rwtm->busy);
return ret;
}
static int turris_mox_rwtm_probe(struct platform_device *pdev)
{
struct mox_rwtm *rwtm;
struct device *dev = &pdev->dev;
int ret;
rwtm = devm_kzalloc(dev, sizeof(*rwtm), GFP_KERNEL);
if (!rwtm)
return -ENOMEM;
rwtm->dev = dev;
rwtm->buf = dmam_alloc_coherent(dev, PAGE_SIZE, &rwtm->buf_phys,
GFP_KERNEL);
if (!rwtm->buf)
return -ENOMEM;
ret = mox_kobj_create(rwtm);
if (ret < 0) {
dev_err(dev, "Cannot create turris-mox-rwtm kobject!\n");
return ret;
}
ret = sysfs_create_files(rwtm_to_kobj(rwtm), mox_rwtm_attrs);
if (ret < 0) {
dev_err(dev, "Cannot create sysfs files!\n");
goto put_kobj;
}
platform_set_drvdata(pdev, rwtm);
mutex_init(&rwtm->busy);
rwtm->mbox_client.dev = dev;
rwtm->mbox_client.rx_callback = mox_rwtm_rx_callback;
rwtm->mbox = mbox_request_channel(&rwtm->mbox_client, 0);
if (IS_ERR(rwtm->mbox)) {
ret = PTR_ERR(rwtm->mbox);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Cannot request mailbox channel: %i\n",
ret);
goto remove_files;
}
init_completion(&rwtm->cmd_done);
ret = mox_get_board_info(rwtm);
if (ret < 0)
dev_warn(dev, "Cannot read board information: %i\n", ret);
rwtm->hwrng.name = DRIVER_NAME "_hwrng";
rwtm->hwrng.read = mox_hwrng_read;
rwtm->hwrng.priv = (unsigned long) rwtm;
rwtm->hwrng.quality = 1024;
ret = devm_hwrng_register(dev, &rwtm->hwrng);
if (ret < 0) {
dev_err(dev, "Cannot register HWRNG: %i\n", ret);
goto free_channel;
}
return 0;
free_channel:
mbox_free_channel(rwtm->mbox);
remove_files:
sysfs_remove_files(rwtm_to_kobj(rwtm), mox_rwtm_attrs);
put_kobj:
kobject_put(rwtm_to_kobj(rwtm));
return ret;
}
static int turris_mox_rwtm_remove(struct platform_device *pdev)
{
struct mox_rwtm *rwtm = platform_get_drvdata(pdev);
sysfs_remove_files(rwtm_to_kobj(rwtm), mox_rwtm_attrs);
kobject_put(rwtm_to_kobj(rwtm));
mbox_free_channel(rwtm->mbox);
return 0;
}
static const struct of_device_id turris_mox_rwtm_match[] = {
{ .compatible = "cznic,turris-mox-rwtm", },
{ },
};
MODULE_DEVICE_TABLE(of, turris_mox_rwtm_match);
static struct platform_driver turris_mox_rwtm_driver = {
.probe = turris_mox_rwtm_probe,
.remove = turris_mox_rwtm_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = turris_mox_rwtm_match,
},
};
module_platform_driver(turris_mox_rwtm_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Turris Mox rWTM firmware driver");
MODULE_AUTHOR("Marek Behun <marek.behun@nic.cz>");
......@@ -1453,6 +1453,15 @@ config GPIO_XRA1403
help
GPIO driver for EXAR XRA1403 16-bit SPI-based GPIO expander.
config GPIO_MOXTET
tristate "Turris Mox Moxtet bus GPIO expander"
depends on MOXTET
help
Say yes here if you are building for the Turris Mox router.
This is the driver needed for configuring the GPIOs via the Moxtet
bus. For example the Mox module with SFP cage needs this driver
so that phylink can use corresponding GPIOs.
endmenu
menu "USB GPIO expanders"
......
......@@ -92,6 +92,7 @@ obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
obj-$(CONFIG_GPIO_MLXBF) += gpio-mlxbf.o
obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o
obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o
obj-$(CONFIG_GPIO_MOXTET) += gpio-moxtet.o
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o
......
// SPDX-License-Identifier: GPL-2.0
/*
* Turris Mox Moxtet GPIO expander
*
* Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
*/
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#include <linux/moxtet.h>
#include <linux/module.h>
#define MOXTET_GPIO_NGPIOS 12
#define MOXTET_GPIO_INPUTS 4
struct moxtet_gpio_desc {
u16 in_mask;
u16 out_mask;
};
static const struct moxtet_gpio_desc descs[] = {
[TURRIS_MOX_MODULE_SFP] = {
.in_mask = GENMASK(2, 0),
.out_mask = GENMASK(5, 4),
},
};
struct moxtet_gpio_chip {
struct device *dev;
struct gpio_chip gpio_chip;
const struct moxtet_gpio_desc *desc;
};
static int moxtet_gpio_get_value(struct gpio_chip *gc, unsigned int offset)
{
struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
int ret;
if (chip->desc->in_mask & BIT(offset)) {
ret = moxtet_device_read(chip->dev);
} else if (chip->desc->out_mask & BIT(offset)) {
ret = moxtet_device_written(chip->dev);
if (ret >= 0)
ret <<= MOXTET_GPIO_INPUTS;
} else {
return -EINVAL;
}
if (ret < 0)
return ret;
return !!(ret & BIT(offset));
}
static void moxtet_gpio_set_value(struct gpio_chip *gc, unsigned int offset,
int val)
{
struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
int state;
state = moxtet_device_written(chip->dev);
if (state < 0)
return;
offset -= MOXTET_GPIO_INPUTS;
if (val)
state |= BIT(offset);
else
state &= ~BIT(offset);
moxtet_device_write(chip->dev, state);
}
static int moxtet_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
{
struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
/* All lines are hard wired to be either input or output, not both. */
if (chip->desc->in_mask & BIT(offset))
return 1;
else if (chip->desc->out_mask & BIT(offset))
return 0;
else
return -EINVAL;
}
static int moxtet_gpio_direction_input(struct gpio_chip *gc,
unsigned int offset)
{
struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
if (chip->desc->in_mask & BIT(offset))
return 0;
else if (chip->desc->out_mask & BIT(offset))
return -ENOTSUPP;
else
return -EINVAL;
}
static int moxtet_gpio_direction_output(struct gpio_chip *gc,
unsigned int offset, int val)
{
struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
if (chip->desc->out_mask & BIT(offset))
moxtet_gpio_set_value(gc, offset, val);
else if (chip->desc->in_mask & BIT(offset))
return -ENOTSUPP;
else
return -EINVAL;
return 0;
}
static int moxtet_gpio_probe(struct device *dev)
{
struct moxtet_gpio_chip *chip;
struct device_node *nc = dev->of_node;
int id;
id = to_moxtet_device(dev)->id;
if (id >= ARRAY_SIZE(descs)) {
dev_err(dev, "%pOF Moxtet device id 0x%x is not supported by gpio-moxtet driver\n",
nc, id);
return -ENOTSUPP;
}
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
chip->dev = dev;
chip->gpio_chip.parent = dev;
chip->desc = &descs[id];
dev_set_drvdata(dev, chip);
chip->gpio_chip.label = dev_name(dev);
chip->gpio_chip.get_direction = moxtet_gpio_get_direction;
chip->gpio_chip.direction_input = moxtet_gpio_direction_input;
chip->gpio_chip.direction_output = moxtet_gpio_direction_output;
chip->gpio_chip.get = moxtet_gpio_get_value;
chip->gpio_chip.set = moxtet_gpio_set_value;
chip->gpio_chip.base = -1;
chip->gpio_chip.ngpio = MOXTET_GPIO_NGPIOS;
chip->gpio_chip.can_sleep = true;
chip->gpio_chip.owner = THIS_MODULE;
return devm_gpiochip_add_data(dev, &chip->gpio_chip, chip);
}
static const struct of_device_id moxtet_gpio_dt_ids[] = {
{ .compatible = "cznic,moxtet-gpio", },
{},
};
MODULE_DEVICE_TABLE(of, moxtet_gpio_dt_ids);
static const enum turris_mox_module_id moxtet_gpio_module_table[] = {
TURRIS_MOX_MODULE_SFP,
0,
};
static struct moxtet_driver moxtet_gpio_driver = {
.driver = {
.name = "moxtet-gpio",
.of_match_table = moxtet_gpio_dt_ids,
.probe = moxtet_gpio_probe,
},
.id_table = moxtet_gpio_module_table,
};
module_moxtet_driver(moxtet_gpio_driver);
MODULE_AUTHOR("Marek Behun <marek.behun@nic.cz>");
MODULE_DESCRIPTION("Turris Mox Moxtet GPIO expander");
MODULE_LICENSE("GPL v2");
......@@ -72,7 +72,7 @@ static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
const struct scmi_handle *h = scmi_sensors->handle;
sensor = *(scmi_sensors->info[type] + channel);
ret = h->sensor_ops->reading_get(h, sensor->id, false, &value);
ret = h->sensor_ops->reading_get(h, sensor->id, &value);
if (ret)
return ret;
......
......@@ -151,7 +151,6 @@ config NET_NETX
To compile this driver as a module, choose M here. The module
will be called netx-eth.
source "drivers/net/ethernet/nuvoton/Kconfig"
source "drivers/net/ethernet/nvidia/Kconfig"
source "drivers/net/ethernet/nxp/Kconfig"
source "drivers/net/ethernet/oki-semi/Kconfig"
......
......@@ -65,7 +65,6 @@ obj-$(CONFIG_NET_VENDOR_NETERION) += neterion/
obj-$(CONFIG_NET_VENDOR_NETRONOME) += netronome/
obj-$(CONFIG_NET_VENDOR_NI) += ni/
obj-$(CONFIG_NET_NETX) += netx-eth.o
obj-$(CONFIG_NET_VENDOR_NUVOTON) += nuvoton/
obj-$(CONFIG_NET_VENDOR_NVIDIA) += nvidia/
obj-$(CONFIG_LPC_ENET) += nxp/
obj-$(CONFIG_NET_VENDOR_OKI) += oki-semi/
......
......@@ -6,8 +6,7 @@
config NET_VENDOR_MICREL
bool "Micrel devices"
default y
depends on (HAS_IOMEM && DMA_ENGINE) || SPI || PCI || HAS_IOMEM || \
(ARM && ARCH_KS8695)
depends on (HAS_IOMEM && DMA_ENGINE) || SPI || PCI || HAS_IOMEM
---help---
If you have a network (Ethernet) card belonging to this class, say Y.
......@@ -18,14 +17,6 @@ config NET_VENDOR_MICREL
if NET_VENDOR_MICREL
config ARM_KS8695_ETHER
tristate "KS8695 Ethernet support"
depends on ARM && ARCH_KS8695
select MII
---help---
If you wish to compile a kernel for the KS8695 and want to
use the internal ethernet then you should answer Y to this.
config KS8842
tristate "Micrel KSZ8841/42 with generic bus interface"
depends on HAS_IOMEM && DMA_ENGINE
......
......@@ -3,7 +3,6 @@
# Makefile for the Micrel network device drivers.
#
obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o
obj-$(CONFIG_KS8842) += ks8842.o
obj-$(CONFIG_KS8851) += ks8851.o
obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Micrel KS8695 (Centaur) Ethernet.
*
* Copyright 2008 Simtec Electronics
* Daniel Silverstone <dsilvers@simtec.co.uk>
* Vincent Sanders <vince@simtec.co.uk>
*/
#ifndef KS8695NET_H
#define KS8695NET_H
/* Receive descriptor flags */
#define RDES_OWN (1 << 31) /* Ownership */
#define RDES_FS (1 << 30) /* First Descriptor */
#define RDES_LS (1 << 29) /* Last Descriptor */
#define RDES_IPE (1 << 28) /* IP Checksum error */
#define RDES_TCPE (1 << 27) /* TCP Checksum error */
#define RDES_UDPE (1 << 26) /* UDP Checksum error */
#define RDES_ES (1 << 25) /* Error summary */
#define RDES_MF (1 << 24) /* Multicast Frame */
#define RDES_RE (1 << 19) /* MII Error reported */
#define RDES_TL (1 << 18) /* Frame too Long */
#define RDES_RF (1 << 17) /* Runt Frame */
#define RDES_CE (1 << 16) /* CRC error */
#define RDES_FT (1 << 15) /* Frame Type */
#define RDES_FLEN (0x7ff) /* Frame Length */
#define RDES_RER (1 << 25) /* Receive End of Ring */
#define RDES_RBS (0x7ff) /* Receive Buffer Size */
/* Transmit descriptor flags */
#define TDES_OWN (1 << 31) /* Ownership */
#define TDES_IC (1 << 31) /* Interrupt on Completion */
#define TDES_FS (1 << 30) /* First Segment */
#define TDES_LS (1 << 29) /* Last Segment */
#define TDES_IPCKG (1 << 28) /* IP Checksum generate */
#define TDES_TCPCKG (1 << 27) /* TCP Checksum generate */
#define TDES_UDPCKG (1 << 26) /* UDP Checksum generate */
#define TDES_TER (1 << 25) /* Transmit End of Ring */
#define TDES_TBS (0x7ff) /* Transmit Buffer Size */
/*
* Network controller register offsets
*/
#define KS8695_DTXC (0x00) /* DMA Transmit Control */
#define KS8695_DRXC (0x04) /* DMA Receive Control */
#define KS8695_DTSC (0x08) /* DMA Transmit Start Command */
#define KS8695_DRSC (0x0c) /* DMA Receive Start Command */
#define KS8695_TDLB (0x10) /* Transmit Descriptor List
* Base Address
*/
#define KS8695_RDLB (0x14) /* Receive Descriptor List
* Base Address
*/
#define KS8695_MAL (0x18) /* MAC Station Address Low */
#define KS8695_MAH (0x1c) /* MAC Station Address High */
#define KS8695_AAL_(n) (0x80 + ((n)*8)) /* MAC Additional
* Station Address
* (0..15) Low
*/
#define KS8695_AAH_(n) (0x84 + ((n)*8)) /* MAC Additional
* Station Address
* (0..15) High
*/
/* DMA Transmit Control Register */
#define DTXC_TRST (1 << 31) /* Soft Reset */
#define DTXC_TBS (0x3f << 24) /* Transmit Burst Size */
#define DTXC_TUCG (1 << 18) /* Transmit UDP
* Checksum Generate
*/
#define DTXC_TTCG (1 << 17) /* Transmit TCP
* Checksum Generate
*/
#define DTXC_TICG (1 << 16) /* Transmit IP
* Checksum Generate
*/
#define DTXC_TFCE (1 << 9) /* Transmit Flow
* Control Enable
*/
#define DTXC_TLB (1 << 8) /* Loopback mode */
#define DTXC_TEP (1 << 2) /* Transmit Enable Padding */
#define DTXC_TAC (1 << 1) /* Transmit Add CRC */
#define DTXC_TE (1 << 0) /* TX Enable */
/* DMA Receive Control Register */
#define DRXC_RBS (0x3f << 24) /* Receive Burst Size */
#define DRXC_RUCC (1 << 18) /* Receive UDP Checksum check */
#define DRXC_RTCG (1 << 17) /* Receive TCP Checksum check */
#define DRXC_RICG (1 << 16) /* Receive IP Checksum check */
#define DRXC_RFCE (1 << 9) /* Receive Flow Control
* Enable
*/
#define DRXC_RB (1 << 6) /* Receive Broadcast */
#define DRXC_RM (1 << 5) /* Receive Multicast */
#define DRXC_RU (1 << 4) /* Receive Unicast */
#define DRXC_RERR (1 << 3) /* Receive Error Frame */
#define DRXC_RA (1 << 2) /* Receive All */
#define DRXC_RE (1 << 0) /* RX Enable */
/* Additional Station Address High */
#define AAH_E (1 << 31) /* Address Enabled */
#endif /* KS8695NET_H */
# SPDX-License-Identifier: GPL-2.0-only
#
# Nuvoton network device configuration
#
config NET_VENDOR_NUVOTON
bool "Nuvoton devices"
default y
depends on ARM && ARCH_W90X900
---help---
If you have a network (Ethernet) card belonging to this class, say Y.
Note that the answer to this question doesn't directly affect the
kernel: saying N will just cause the configurator to skip all
the questions about Nuvoton cards. If you say Y, you will be asked
for your specific card in the following questions.
if NET_VENDOR_NUVOTON
config W90P910_ETH
tristate "Nuvoton w90p910 Ethernet support"
depends on ARM && ARCH_W90X900
select PHYLIB
select MII
---help---
Say Y here if you want to use built-in Ethernet ports
on w90p910 processor.
endif # NET_VENDOR_NUVOTON
# SPDX-License-Identifier: GPL-2.0-only
#
# Makefile for the Nuvoton network device drivers.
#
obj-$(CONFIG_W90P910_ETH) += w90p910_ether.o
This diff is collapsed.
......@@ -116,9 +116,20 @@ config RESET_QCOM_PDC
to control reset signals provided by PDC for Modem, Compute,
Display, GPU, Debug, AOP, Sensors, Audio, SP and APPS.
config RESET_SCMI
tristate "Reset driver controlled via ARM SCMI interface"
depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
default ARM_SCMI_PROTOCOL
help
This driver provides support for reset signal/domains that are
controlled by firmware that implements the SCMI interface.
This driver uses SCMI Message Protocol to interact with the
firmware controlling all the reset signals.
config RESET_SIMPLE
bool "Simple Reset Controller Driver" if COMPILE_TEST
default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED || ARCH_BITMAIN
default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED || ARCH_BITMAIN || ARC
help
This enables a simple reset controller driver for reset lines that
that can be asserted and deasserted by toggling bits in a contiguous,
......
......@@ -18,6 +18,7 @@ obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o
obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
......
......@@ -169,9 +169,9 @@ static const struct imx7_src_signal imx8mq_src_signals[IMX8MQ_RESET_NUM] = {
[IMX8MQ_RESET_OTG2_PHY_RESET] = { SRC_USBOPHY2_RCR, BIT(0) },
[IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N] = { SRC_MIPIPHY_RCR, BIT(1) },
[IMX8MQ_RESET_MIPI_DSI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(2) },
[IMX8MQ_RESET_MIPI_DIS_DPI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(3) },
[IMX8MQ_RESET_MIPI_DIS_ESC_RESET_N] = { SRC_MIPIPHY_RCR, BIT(4) },
[IMX8MQ_RESET_MIPI_DIS_PCLK_RESET_N] = { SRC_MIPIPHY_RCR, BIT(5) },
[IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N] = { SRC_MIPIPHY_RCR, BIT(3) },
[IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N] = { SRC_MIPIPHY_RCR, BIT(4) },
[IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N] = { SRC_MIPIPHY_RCR, BIT(5) },
[IMX8MQ_RESET_PCIEPHY] = { SRC_PCIEPHY_RCR,
BIT(2) | BIT(1) },
[IMX8MQ_RESET_PCIEPHY_PERST] = { SRC_PCIEPHY_RCR, BIT(3) },
......@@ -220,9 +220,9 @@ static int imx8mq_reset_set(struct reset_controller_dev *rcdev,
case IMX8MQ_RESET_PCIE_CTRL_APPS_EN:
case IMX8MQ_RESET_PCIE2_CTRL_APPS_EN: /* fallthrough */
case IMX8MQ_RESET_MIPI_DIS_PCLK_RESET_N: /* fallthrough */
case IMX8MQ_RESET_MIPI_DIS_ESC_RESET_N: /* fallthrough */
case IMX8MQ_RESET_MIPI_DIS_DPI_RESET_N: /* fallthrough */
case IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N: /* fallthrough */
case IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N: /* fallthrough */
case IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N: /* fallthrough */
case IMX8MQ_RESET_MIPI_DSI_RESET_N: /* fallthrough */
case IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N: /* fallthrough */
value = assert ? 0 : bit;
......
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Amlogic Meson Reset Controller driver
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright (c) 2016 BayLibre, SAS.
* Author: Neil Armstrong <narmstrong@baylibre.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* BSD LICENSE
*
* Copyright (c) 2016 BayLibre, SAS.
* Author: Neil Armstrong <narmstrong@baylibre.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/err.h>
#include <linux/init.h>
......
// SPDX-License-Identifier: GPL-2.0
/*
* ARM System Control and Management Interface (ARM SCMI) reset driver
*
* Copyright (C) 2019 ARM Ltd.
*/
#include <linux/module.h>
#include <linux/of.h>
#include <linux/device.h>
#include <linux/reset-controller.h>
#include <linux/scmi_protocol.h>
/**
* struct scmi_reset_data - reset controller information structure
* @rcdev: reset controller entity
* @handle: ARM SCMI handle used for communication with system controller
*/
struct scmi_reset_data {
struct reset_controller_dev rcdev;
const struct scmi_handle *handle;
};
#define to_scmi_reset_data(p) container_of((p), struct scmi_reset_data, rcdev)
#define to_scmi_handle(p) (to_scmi_reset_data(p)->handle)
/**
* scmi_reset_assert() - assert device reset
* @rcdev: reset controller entity
* @id: ID of the reset to be asserted
*
* This function implements the reset driver op to assert a device's reset
* using the ARM SCMI protocol.
*
* Return: 0 for successful request, else a corresponding error value
*/
static int
scmi_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
{
const struct scmi_handle *handle = to_scmi_handle(rcdev);
return handle->reset_ops->assert(handle, id);
}
/**
* scmi_reset_deassert() - deassert device reset
* @rcdev: reset controller entity
* @id: ID of the reset to be deasserted
*
* This function implements the reset driver op to deassert a device's reset
* using the ARM SCMI protocol.
*
* Return: 0 for successful request, else a corresponding error value
*/
static int
scmi_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
{
const struct scmi_handle *handle = to_scmi_handle(rcdev);
return handle->reset_ops->deassert(handle, id);
}
/**
* scmi_reset_reset() - reset the device
* @rcdev: reset controller entity
* @id: ID of the reset signal to be reset(assert + deassert)
*
* This function implements the reset driver op to trigger a device's
* reset signal using the ARM SCMI protocol.
*
* Return: 0 for successful request, else a corresponding error value
*/
static int
scmi_reset_reset(struct reset_controller_dev *rcdev, unsigned long id)
{
const struct scmi_handle *handle = to_scmi_handle(rcdev);
return handle->reset_ops->reset(handle, id);
}
static const struct reset_control_ops scmi_reset_ops = {
.assert = scmi_reset_assert,
.deassert = scmi_reset_deassert,
.reset = scmi_reset_reset,
};
static int scmi_reset_probe(struct scmi_device *sdev)
{
struct scmi_reset_data *data;
struct device *dev = &sdev->dev;
struct device_node *np = dev->of_node;
const struct scmi_handle *handle = sdev->handle;
if (!handle || !handle->reset_ops)
return -ENODEV;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->rcdev.ops = &scmi_reset_ops;
data->rcdev.owner = THIS_MODULE;
data->rcdev.of_node = np;
data->rcdev.nr_resets = handle->reset_ops->num_domains_get(handle);
return devm_reset_controller_register(dev, &data->rcdev);
}
static const struct scmi_device_id scmi_id_table[] = {
{ SCMI_PROTOCOL_RESET },
{ },
};
MODULE_DEVICE_TABLE(scmi, scmi_id_table);
static struct scmi_driver scmi_reset_driver = {
.name = "scmi-reset",
.probe = scmi_reset_probe,
.id_table = scmi_id_table,
};
module_scmi_driver(scmi_reset_driver);
MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
MODULE_DESCRIPTION("ARM SCMI reset controller driver");
MODULE_LICENSE("GPL v2");
......@@ -127,6 +127,9 @@ static const struct of_device_id reset_simple_dt_ids[] = {
{ .compatible = "aspeed,ast2500-lpc-reset" },
{ .compatible = "bitmain,bm1880-reset",
.data = &reset_simple_active_low },
{ .compatible = "snps,dw-high-reset" },
{ .compatible = "snps,dw-low-reset",
.data = &reset_simple_active_low },
{ /* sentinel */ },
};
......
......@@ -37,6 +37,17 @@ config MESON_GX_PM_DOMAINS
Say yes to expose Amlogic Meson GX Power Domains as
Generic Power Domains.
config MESON_EE_PM_DOMAINS
bool "Amlogic Meson Everything-Else Power Domains driver"
depends on ARCH_MESON || COMPILE_TEST
depends on PM && OF
default ARCH_MESON
select PM_GENERIC_DOMAINS
select PM_GENERIC_DOMAINS_OF
help
Say yes to expose Amlogic Meson Everything-Else Power Domains as
Generic Power Domains.
config MESON_MX_SOCINFO
bool "Amlogic Meson MX SoC Information driver"
depends on ARCH_MESON || COMPILE_TEST
......
......@@ -4,3 +4,4 @@ obj-$(CONFIG_MESON_CLK_MEASURE) += meson-clk-measure.o
obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o
obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o
obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o
obj-$(CONFIG_MESON_EE_PM_DOMAINS) += meson-ee-pwrc.o
......@@ -11,6 +11,8 @@
#include <linux/debugfs.h>
#include <linux/regmap.h>
static DEFINE_MUTEX(measure_lock);
#define MSR_CLK_DUTY 0x0
#define MSR_CLK_REG0 0x4
#define MSR_CLK_REG1 0x8
......@@ -322,6 +324,8 @@ static struct meson_msr_id clk_msr_g12a[CLK_MSR_MAX] = {
CLK_MSR_ID(84, "co_tx"),
CLK_MSR_ID(89, "hdmi_todig"),
CLK_MSR_ID(90, "hdmitx_sys"),
CLK_MSR_ID(91, "sys_cpub_div16"),
CLK_MSR_ID(92, "sys_pll_cpub_div16"),
CLK_MSR_ID(94, "eth_phy_rx"),
CLK_MSR_ID(95, "eth_phy_pll"),
CLK_MSR_ID(96, "vpu_b"),
......@@ -353,6 +357,136 @@ static struct meson_msr_id clk_msr_g12a[CLK_MSR_MAX] = {
CLK_MSR_ID(122, "audio_pdm_dclk"),
};
static struct meson_msr_id clk_msr_sm1[CLK_MSR_MAX] = {
CLK_MSR_ID(0, "ring_osc_out_ee_0"),
CLK_MSR_ID(1, "ring_osc_out_ee_1"),
CLK_MSR_ID(2, "ring_osc_out_ee_2"),
CLK_MSR_ID(3, "ring_osc_out_ee_3"),
CLK_MSR_ID(4, "gp0_pll"),
CLK_MSR_ID(5, "gp1_pll"),
CLK_MSR_ID(6, "enci"),
CLK_MSR_ID(7, "clk81"),
CLK_MSR_ID(8, "encp"),
CLK_MSR_ID(9, "encl"),
CLK_MSR_ID(10, "vdac"),
CLK_MSR_ID(11, "eth_tx"),
CLK_MSR_ID(12, "hifi_pll"),
CLK_MSR_ID(13, "mod_tcon"),
CLK_MSR_ID(14, "fec_0"),
CLK_MSR_ID(15, "fec_1"),
CLK_MSR_ID(16, "fec_2"),
CLK_MSR_ID(17, "sys_pll_div16"),
CLK_MSR_ID(18, "sys_cpu_div16"),
CLK_MSR_ID(19, "lcd_an_ph2"),
CLK_MSR_ID(20, "rtc_osc_out"),
CLK_MSR_ID(21, "lcd_an_ph3"),
CLK_MSR_ID(22, "eth_phy_ref"),
CLK_MSR_ID(23, "mpll_50m"),
CLK_MSR_ID(24, "eth_125m"),
CLK_MSR_ID(25, "eth_rmii"),
CLK_MSR_ID(26, "sc_int"),
CLK_MSR_ID(27, "in_mac"),
CLK_MSR_ID(28, "sar_adc"),
CLK_MSR_ID(29, "pcie_inp"),
CLK_MSR_ID(30, "pcie_inn"),
CLK_MSR_ID(31, "mpll_test_out"),
CLK_MSR_ID(32, "vdec"),
CLK_MSR_ID(34, "eth_mpll_50m"),
CLK_MSR_ID(35, "mali"),
CLK_MSR_ID(36, "hdmi_tx_pixel"),
CLK_MSR_ID(37, "cdac"),
CLK_MSR_ID(38, "vdin_meas"),
CLK_MSR_ID(39, "bt656"),
CLK_MSR_ID(40, "arm_ring_osc_out_4"),
CLK_MSR_ID(41, "eth_rx_or_rmii"),
CLK_MSR_ID(42, "mp0_out"),
CLK_MSR_ID(43, "fclk_div5"),
CLK_MSR_ID(44, "pwm_b"),
CLK_MSR_ID(45, "pwm_a"),
CLK_MSR_ID(46, "vpu"),
CLK_MSR_ID(47, "ddr_dpll_pt"),
CLK_MSR_ID(48, "mp1_out"),
CLK_MSR_ID(49, "mp2_out"),
CLK_MSR_ID(50, "mp3_out"),
CLK_MSR_ID(51, "sd_emmc_c"),
CLK_MSR_ID(52, "sd_emmc_b"),
CLK_MSR_ID(53, "sd_emmc_a"),
CLK_MSR_ID(54, "vpu_clkc"),
CLK_MSR_ID(55, "vid_pll_div_out"),
CLK_MSR_ID(56, "wave420l_a"),
CLK_MSR_ID(57, "wave420l_c"),
CLK_MSR_ID(58, "wave420l_b"),
CLK_MSR_ID(59, "hcodec"),
CLK_MSR_ID(60, "arm_ring_osc_out_5"),
CLK_MSR_ID(61, "gpio_msr"),
CLK_MSR_ID(62, "hevcb"),
CLK_MSR_ID(63, "dsi_meas"),
CLK_MSR_ID(64, "spicc_1"),
CLK_MSR_ID(65, "spicc_0"),
CLK_MSR_ID(66, "vid_lock"),
CLK_MSR_ID(67, "dsi_phy"),
CLK_MSR_ID(68, "hdcp22_esm"),
CLK_MSR_ID(69, "hdcp22_skp"),
CLK_MSR_ID(70, "pwm_f"),
CLK_MSR_ID(71, "pwm_e"),
CLK_MSR_ID(72, "pwm_d"),
CLK_MSR_ID(73, "pwm_c"),
CLK_MSR_ID(74, "arm_ring_osc_out_6"),
CLK_MSR_ID(75, "hevcf"),
CLK_MSR_ID(76, "arm_ring_osc_out_7"),
CLK_MSR_ID(77, "rng_ring_osc_0"),
CLK_MSR_ID(78, "rng_ring_osc_1"),
CLK_MSR_ID(79, "rng_ring_osc_2"),
CLK_MSR_ID(80, "rng_ring_osc_3"),
CLK_MSR_ID(81, "vapb"),
CLK_MSR_ID(82, "ge2d"),
CLK_MSR_ID(83, "co_rx"),
CLK_MSR_ID(84, "co_tx"),
CLK_MSR_ID(85, "arm_ring_osc_out_8"),
CLK_MSR_ID(86, "arm_ring_osc_out_9"),
CLK_MSR_ID(87, "mipi_dsi_phy"),
CLK_MSR_ID(88, "cis2_adapt"),
CLK_MSR_ID(89, "hdmi_todig"),
CLK_MSR_ID(90, "hdmitx_sys"),
CLK_MSR_ID(91, "nna_core"),
CLK_MSR_ID(92, "nna_axi"),
CLK_MSR_ID(93, "vad"),
CLK_MSR_ID(94, "eth_phy_rx"),
CLK_MSR_ID(95, "eth_phy_pll"),
CLK_MSR_ID(96, "vpu_b"),
CLK_MSR_ID(97, "cpu_b_tmp"),
CLK_MSR_ID(98, "ts"),
CLK_MSR_ID(99, "arm_ring_osc_out_10"),
CLK_MSR_ID(100, "arm_ring_osc_out_11"),
CLK_MSR_ID(101, "arm_ring_osc_out_12"),
CLK_MSR_ID(102, "arm_ring_osc_out_13"),
CLK_MSR_ID(103, "arm_ring_osc_out_14"),
CLK_MSR_ID(104, "arm_ring_osc_out_15"),
CLK_MSR_ID(105, "arm_ring_osc_out_16"),
CLK_MSR_ID(106, "ephy_test"),
CLK_MSR_ID(107, "au_dac_g128x"),
CLK_MSR_ID(108, "audio_locker_out"),
CLK_MSR_ID(109, "audio_locker_in"),
CLK_MSR_ID(110, "audio_tdmout_c_sclk"),
CLK_MSR_ID(111, "audio_tdmout_b_sclk"),
CLK_MSR_ID(112, "audio_tdmout_a_sclk"),
CLK_MSR_ID(113, "audio_tdmin_lb_sclk"),
CLK_MSR_ID(114, "audio_tdmin_c_sclk"),
CLK_MSR_ID(115, "audio_tdmin_b_sclk"),
CLK_MSR_ID(116, "audio_tdmin_a_sclk"),
CLK_MSR_ID(117, "audio_resample"),
CLK_MSR_ID(118, "audio_pdm_sys"),
CLK_MSR_ID(119, "audio_spdifout_b"),
CLK_MSR_ID(120, "audio_spdifout"),
CLK_MSR_ID(121, "audio_spdifin"),
CLK_MSR_ID(122, "audio_pdm_dclk"),
CLK_MSR_ID(123, "audio_resampled"),
CLK_MSR_ID(124, "earcrx_pll"),
CLK_MSR_ID(125, "earcrx_pll_test"),
CLK_MSR_ID(126, "csi_phy0"),
CLK_MSR_ID(127, "csi2_data"),
};
static int meson_measure_id(struct meson_msr_id *clk_msr_id,
unsigned int duration)
{
......@@ -360,6 +494,10 @@ static int meson_measure_id(struct meson_msr_id *clk_msr_id,
unsigned int val;
int ret;
ret = mutex_lock_interruptible(&measure_lock);
if (ret)
return ret;
regmap_write(priv->regmap, MSR_CLK_REG0, 0);
/* Set measurement duration */
......@@ -377,8 +515,10 @@ static int meson_measure_id(struct meson_msr_id *clk_msr_id,
ret = regmap_read_poll_timeout(priv->regmap, MSR_CLK_REG0,
val, !(val & MSR_BUSY), 10, 10000);
if (ret)
if (ret) {
mutex_unlock(&measure_lock);
return ret;
}
/* Disable */
regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_ENABLE, 0);
......@@ -386,6 +526,8 @@ static int meson_measure_id(struct meson_msr_id *clk_msr_id,
/* Get the value in multiple of gate time counts */
regmap_read(priv->regmap, MSR_CLK_REG2, &val);
mutex_unlock(&measure_lock);
if (val >= MSR_VAL_MASK)
return -EINVAL;
......@@ -533,6 +675,10 @@ static const struct of_device_id meson_msr_match_table[] = {
.compatible = "amlogic,meson-g12a-clk-measure",
.data = (void *)clk_msr_g12a,
},
{
.compatible = "amlogic,meson-sm1-clk-measure",
.data = (void *)clk_msr_sm1,
},
{ /* sentinel */ }
};
......
This diff is collapsed.
......@@ -39,6 +39,7 @@ static const struct meson_gx_soc_id {
{ "TXHD", 0x27 },
{ "G12A", 0x28 },
{ "G12B", 0x29 },
{ "SM1", 0x2b },
};
static const struct meson_gx_package_id {
......@@ -65,6 +66,8 @@ static const struct meson_gx_package_id {
{ "S905D2", 0x28, 0x10, 0xf0 },
{ "S905X2", 0x28, 0x40, 0xf0 },
{ "S922X", 0x29, 0x40, 0xf0 },
{ "A311D", 0x29, 0x10, 0xf0 },
{ "S905X3", 0x2b, 0x5, 0xf },
};
static inline unsigned int socinfo_to_major(u32 socinfo)
......@@ -138,8 +141,10 @@ static int __init meson_gx_socinfo_init(void)
}
/* check if chip-id is available */
if (!of_property_read_bool(np, "amlogic,has-chip-id"))
if (!of_property_read_bool(np, "amlogic,has-chip-id")) {
of_node_put(np);
return -ENODEV;
}
/* node should be a syscon */
regmap = syscon_node_to_regmap(np);
......
......@@ -73,7 +73,7 @@ static u64 get_mc_fw_base_address(void)
mcfbaregs = ioremap(mc_base_addr.start, resource_size(&mc_base_addr));
if (!mcfbaregs) {
pr_err("could not map MC Firmaware Base registers\n");
pr_err("could not map MC Firmware Base registers\n");
return 0;
}
......
......@@ -305,8 +305,6 @@ void dpaa2_io_service_deregister(struct dpaa2_io *service,
list_del(&ctx->node);
spin_unlock_irqrestore(&d->lock_notifications, irqflags);
if (dev)
device_link_remove(dev, d->dev);
}
EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister);
......
......@@ -102,6 +102,11 @@ static const struct fsl_soc_die_attr fsl_soc_die[] = {
.svr = 0x87360000,
.mask = 0xff3f0000,
},
/* Die: LS1028A, SoC: LS1028A */
{ .die = "LS1028A",
.svr = 0x870b0000,
.mask = 0xff3f0000,
},
{ },
};
......@@ -224,6 +229,7 @@ static const struct of_device_id fsl_guts_of_match[] = {
{ .compatible = "fsl,ls1012a-dcfg", },
{ .compatible = "fsl,ls1046a-dcfg", },
{ .compatible = "fsl,lx2160a-dcfg", },
{ .compatible = "fsl,ls1028a-dcfg", },
{}
};
MODULE_DEVICE_TABLE(of, fsl_guts_of_match);
......
......@@ -635,30 +635,31 @@ int bman_p_irqsource_add(struct bman_portal *p, u32 bits)
return 0;
}
static int bm_shutdown_pool(u32 bpid)
int bm_shutdown_pool(u32 bpid)
{
int err = 0;
struct bm_mc_command *bm_cmd;
union bm_mc_result *bm_res;
struct bman_portal *p = get_affine_portal();
while (1) {
struct bman_portal *p = get_affine_portal();
/* Acquire buffers until empty */
bm_cmd = bm_mc_start(&p->p);
bm_cmd->bpid = bpid;
bm_mc_commit(&p->p, BM_MCC_VERB_CMD_ACQUIRE | 1);
if (!bm_mc_result_timeout(&p->p, &bm_res)) {
put_affine_portal();
pr_crit("BMan Acquire Command timedout\n");
return -ETIMEDOUT;
err = -ETIMEDOUT;
goto done;
}
if (!(bm_res->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT)) {
put_affine_portal();
/* Pool is empty */
return 0;
goto done;
}
put_affine_portal();
}
done:
put_affine_portal();
return 0;
}
......
......@@ -97,17 +97,40 @@ static void bm_get_version(u16 *id, u8 *major, u8 *minor)
/* signal transactions for FBPRs with higher priority */
#define FBPR_AR_RPRIO_HI BIT(30)
static void bm_set_memory(u64 ba, u32 size)
/* Track if probe has occurred and if cleanup is required */
static int __bman_probed;
static int __bman_requires_cleanup;
static int bm_set_memory(u64 ba, u32 size)
{
u32 bar, bare;
u32 exp = ilog2(size);
/* choke if size isn't within range */
DPAA_ASSERT(size >= 4096 && size <= 1024*1024*1024 &&
is_power_of_2(size));
/* choke if '[e]ba' has lower-alignment than 'size' */
DPAA_ASSERT(!(ba & (size - 1)));
/* Check to see if BMan has already been initialized */
bar = bm_ccsr_in(REG_FBPR_BAR);
if (bar) {
/* Maker sure ba == what was programmed) */
bare = bm_ccsr_in(REG_FBPR_BARE);
if (bare != upper_32_bits(ba) || bar != lower_32_bits(ba)) {
pr_err("Attempted to reinitialize BMan with different BAR, got 0x%llx read BARE=0x%x BAR=0x%x\n",
ba, bare, bar);
return -ENOMEM;
}
pr_info("BMan BAR already configured\n");
__bman_requires_cleanup = 1;
return 1;
}
bm_ccsr_out(REG_FBPR_BARE, upper_32_bits(ba));
bm_ccsr_out(REG_FBPR_BAR, lower_32_bits(ba));
bm_ccsr_out(REG_FBPR_AR, exp - 1);
return 0;
}
/*
......@@ -120,7 +143,6 @@ static void bm_set_memory(u64 ba, u32 size)
*/
static dma_addr_t fbpr_a;
static size_t fbpr_sz;
static int __bman_probed;
static int bman_fbpr(struct reserved_mem *rmem)
{
......@@ -173,6 +195,16 @@ int bman_is_probed(void)
}
EXPORT_SYMBOL_GPL(bman_is_probed);
int bman_requires_cleanup(void)
{
return __bman_requires_cleanup;
}
void bman_done_cleanup(void)
{
__bman_requires_cleanup = 0;
}
static int fsl_bman_probe(struct platform_device *pdev)
{
int ret, err_irq;
......
......@@ -100,7 +100,7 @@ static int bman_portal_probe(struct platform_device *pdev)
struct device_node *node = dev->of_node;
struct bm_portal_config *pcfg;
struct resource *addr_phys[2];
int irq, cpu, err;
int irq, cpu, err, i;
err = bman_is_probed();
if (!err)
......@@ -135,10 +135,8 @@ static int bman_portal_probe(struct platform_device *pdev)
pcfg->cpu = -1;
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(dev, "Can't get %pOF IRQ'\n", node);
if (irq <= 0)
goto err_ioremap1;
}
pcfg->irq = irq;
pcfg->addr_virt_ce = memremap(addr_phys[0]->start,
......@@ -178,6 +176,22 @@ static int bman_portal_probe(struct platform_device *pdev)
if (!cpu_online(cpu))
bman_offline_cpu(cpu);
if (__bman_portals_probed == 1 && bman_requires_cleanup()) {
/*
* BMan wasn't reset prior to boot (Kexec for example)
* Empty all the buffer pools so they are in reset state
*/
for (i = 0; i < BM_POOL_MAX; i++) {
err = bm_shutdown_pool(i);
if (err) {
dev_err(dev, "Failed to shutdown bpool %d\n",
i);
goto err_portal_init;
}
}
bman_done_cleanup();
}
return 0;
err_portal_init:
......
......@@ -76,3 +76,8 @@ int bman_p_irqsource_add(struct bman_portal *p, u32 bits);
const struct bm_portal_config *
bman_get_bm_portal_config(const struct bman_portal *portal);
int bman_requires_cleanup(void);
void bman_done_cleanup(void);
int bm_shutdown_pool(u32 bpid);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -198,7 +198,7 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
err = regulator_disable(domain->regulator);
if (err)
dev_err(domain->dev,
"failed to disable regulator: %d\n", ret);
"failed to disable regulator: %d\n", err);
/* Preserve earlier error code */
ret = ret ?: err;
}
......
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.
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