From 5d1d046e2868fc876a69231eb2f24f000b521f1c Mon Sep 17 00:00:00 2001 From: Laurentiu Tudor Date: Sat, 27 Apr 2019 10:10:24 +0300 Subject: soc: fsl: qbman_portals: add APIs to retrieve the probing status Add a couple of new APIs to check the probing status of the required cpu bound qman and bman portals: 'int bman_portals_probed()' and 'int qman_portals_probed()'. They return the following values. * 1 if qman/bman portals were all probed correctly * 0 if qman/bman portals were not yet probed * -1 if probing of qman/bman portals failed Portals are considered successful probed if no error occurred during the probing of any of the portals and if enough portals were probed to have one available for each cpu. The error handling paths were slightly rearranged in order to fit this new functionality without being too intrusive. Drivers that use qman/bman portal driver services are required to use these APIs before calling any functions exported by these drivers or otherwise they will crash the kernel. First user will be the dpaa1 ethernet driver, coming in a subsequent patch. Signed-off-by: Laurentiu Tudor Signed-off-by: Li Yang --- include/soc/fsl/bman.h | 8 ++++++++ include/soc/fsl/qman.h | 9 +++++++++ 2 files changed, 17 insertions(+) (limited to 'include') diff --git a/include/soc/fsl/bman.h b/include/soc/fsl/bman.h index 5b99cb2ea5ef..173e4049d963 100644 --- a/include/soc/fsl/bman.h +++ b/include/soc/fsl/bman.h @@ -133,5 +133,13 @@ int bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, u8 num); * failed to probe or 0 if the bman driver did not probed yet. */ int bman_is_probed(void); +/** + * bman_portals_probed - Check if all cpu bound bman portals are probed + * + * Returns 1 if all the required cpu bound bman portals successfully probed, + * -1 if probe errors appeared or 0 if the bman portals did not yet finished + * probing. + */ +int bman_portals_probed(void); #endif /* __FSL_BMAN_H */ diff --git a/include/soc/fsl/qman.h b/include/soc/fsl/qman.h index 5cc7af06c1ba..aa31c05a103a 100644 --- a/include/soc/fsl/qman.h +++ b/include/soc/fsl/qman.h @@ -1194,6 +1194,15 @@ int qman_release_cgrid(u32 id); */ int qman_is_probed(void); +/** + * qman_portals_probed - Check if all cpu bound qman portals are probed + * + * Returns 1 if all the required cpu bound qman portals successfully probed, + * -1 if probe errors appeared or 0 if the qman portals did not yet finished + * probing. + */ +int qman_portals_probed(void); + /** * qman_dqrr_get_ithresh - Get coalesce interrupt threshold * @portal: portal to get the value for -- cgit v1.2.3 From ef98682a4e1257ff45405bb1372939e8dfe774bb Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Sat, 11 May 2019 00:15:22 +0530 Subject: dt-bindings: reset: Add devicetree binding for BM1880 reset controller Add devicetree binding for Bitmain BM1880 SoC reset controller. Signed-off-by: Manivannan Sadhasivam Reviewed-by: Rob Herring Signed-off-by: Philipp Zabel --- .../bindings/reset/bitmain,bm1880-reset.txt | 18 ++++++++ include/dt-bindings/reset/bitmain,bm1880-reset.h | 51 ++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 Documentation/devicetree/bindings/reset/bitmain,bm1880-reset.txt create mode 100644 include/dt-bindings/reset/bitmain,bm1880-reset.h (limited to 'include') diff --git a/Documentation/devicetree/bindings/reset/bitmain,bm1880-reset.txt b/Documentation/devicetree/bindings/reset/bitmain,bm1880-reset.txt new file mode 100644 index 000000000000..a6f8455ae6c4 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/bitmain,bm1880-reset.txt @@ -0,0 +1,18 @@ +Bitmain BM1880 SoC Reset Controller +=================================== + +Please also refer to reset.txt in this directory for common reset +controller binding usage. + +Required properties: +- compatible: Should be "bitmain,bm1880-reset" +- reg: Offset and length of reset controller space in SCTRL. +- #reset-cells: Must be 1. + +Example: + + rst: reset-controller@c00 { + compatible = "bitmain,bm1880-reset"; + reg = <0xc00 0x8>; + #reset-cells = <1>; + }; diff --git a/include/dt-bindings/reset/bitmain,bm1880-reset.h b/include/dt-bindings/reset/bitmain,bm1880-reset.h new file mode 100644 index 000000000000..4c0de5223773 --- /dev/null +++ b/include/dt-bindings/reset/bitmain,bm1880-reset.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2018 Bitmain Ltd. + * Copyright (c) 2019 Linaro Ltd. + */ + +#ifndef _DT_BINDINGS_BM1880_RESET_H +#define _DT_BINDINGS_BM1880_RESET_H + +#define BM1880_RST_MAIN_AP 0 +#define BM1880_RST_SECOND_AP 1 +#define BM1880_RST_DDR 2 +#define BM1880_RST_VIDEO 3 +#define BM1880_RST_JPEG 4 +#define BM1880_RST_VPP 5 +#define BM1880_RST_GDMA 6 +#define BM1880_RST_AXI_SRAM 7 +#define BM1880_RST_TPU 8 +#define BM1880_RST_USB 9 +#define BM1880_RST_ETH0 10 +#define BM1880_RST_ETH1 11 +#define BM1880_RST_NAND 12 +#define BM1880_RST_EMMC 13 +#define BM1880_RST_SD 14 +#define BM1880_RST_SDMA 15 +#define BM1880_RST_I2S0 16 +#define BM1880_RST_I2S1 17 +#define BM1880_RST_UART0_1_CLK 18 +#define BM1880_RST_UART0_1_ACLK 19 +#define BM1880_RST_UART2_3_CLK 20 +#define BM1880_RST_UART2_3_ACLK 21 +#define BM1880_RST_MINER 22 +#define BM1880_RST_I2C0 23 +#define BM1880_RST_I2C1 24 +#define BM1880_RST_I2C2 25 +#define BM1880_RST_I2C3 26 +#define BM1880_RST_I2C4 27 +#define BM1880_RST_PWM0 28 +#define BM1880_RST_PWM1 29 +#define BM1880_RST_PWM2 30 +#define BM1880_RST_PWM3 31 +#define BM1880_RST_SPI 32 +#define BM1880_RST_GPIO0 33 +#define BM1880_RST_GPIO1 34 +#define BM1880_RST_GPIO2 35 +#define BM1880_RST_EFUSE 36 +#define BM1880_RST_WDT 37 +#define BM1880_RST_AHB_ROM 38 +#define BM1880_RST_SPIC 39 + +#endif /* _DT_BINDINGS_BM1880_RESET_H */ -- cgit v1.2.3 From 2b2f7def058a5386838ef4dba70a860285f79e66 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 27 May 2019 04:51:53 -0700 Subject: bus: ti-sysc: Add support for missing clockdomain handling We need to let ti-sysc driver manage clockdomain autoidle for the duration of of reset, enable and idle. And we need to do it before we enable the clock and after we disable it. Currently we are still relying on platform callbacks indirectly managing clockdomain autoidle. But I noticed that for device tree only probed drivers it now happens only after we enabling the clocks and before we disable the clocks, while it should be the other way around. So far I have not noticed any issues with this though. Let's add new ti_sysc_clkdm_deny_idle() and ti_sysc_clkdm_allow_idle() functions for ti-sysc driver to use to manage clockdomains directly via platform data callbacks. Note that we can implement the clockdomain functions in pdata-quirks.c as for probing devices without "ti,hwmods" custom property we don't need to use the other platform data callbacks. Let's do this in one patch as there's is still an unlikely chance we may need to apply this as a fix for v5.2 for dropping legacy platform data for some devices. We also do have the option of adding back the platform data if needed in case of trouble. Tested-by: Keerthy Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod.c | 39 ++--------- arch/arm/mach-omap2/pdata-quirks.c | 60 ++++++++++++++++ drivers/bus/ti-sysc.c | 127 +++++++++++++++++++++++++++------- include/linux/platform_data/ti-sysc.h | 8 +++ 4 files changed, 174 insertions(+), 60 deletions(-) (limited to 'include') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 405ac24def05..932ba221e8e7 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -3445,6 +3445,7 @@ static int omap_hwmod_check_module(struct device *dev, * @dev: struct device * @oh: module * @sysc_fields: sysc register bits + * @clockdomain: clockdomain * @rev_offs: revision register offset * @sysc_offs: sysconfig register offset * @syss_offs: sysstatus register offset @@ -3456,6 +3457,7 @@ static int omap_hwmod_check_module(struct device *dev, static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, const struct ti_sysc_module_data *data, struct sysc_regbits *sysc_fields, + struct clockdomain *clkdm, s32 rev_offs, s32 sysc_offs, s32 syss_offs, u32 sysc_flags, u32 idlemodes) @@ -3463,8 +3465,6 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, struct omap_hwmod_class_sysconfig *sysc; struct omap_hwmod_class *class = NULL; struct omap_hwmod_ocp_if *oi = NULL; - struct clockdomain *clkdm = NULL; - struct clk *clk = NULL; void __iomem *regs = NULL; unsigned long flags; @@ -3511,36 +3511,6 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, oi->user = OCP_USER_MPU | OCP_USER_SDMA; } - if (!oh->_clk) { - struct clk_hw_omap *hwclk; - - clk = of_clk_get_by_name(dev->of_node, "fck"); - if (!IS_ERR(clk)) - clk_prepare(clk); - else - clk = NULL; - - /* - * Populate clockdomain based on dts clock. It is needed for - * clkdm_deny_idle() and clkdm_allow_idle() until we have have - * interconnect driver and reset driver capable of blocking - * clockdomain idle during reset, enable and idle. - */ - if (clk) { - hwclk = to_clk_hw_omap(__clk_get_hw(clk)); - if (hwclk && hwclk->clkdm_name) - clkdm = clkdm_lookup(hwclk->clkdm_name); - } - - /* - * Note that we assume interconnect driver manages the clocks - * and do not need to populate oh->_clk for dynamically - * allocated modules. - */ - clk_unprepare(clk); - clk_put(clk); - } - spin_lock_irqsave(&oh->_lock, flags); if (regs) oh->_mpu_rt_va = regs; @@ -3626,7 +3596,7 @@ int omap_hwmod_init_module(struct device *dev, u32 sysc_flags, idlemodes; int error; - if (!dev || !data) + if (!dev || !data || !data->name || !cookie) return -EINVAL; oh = _lookup(data->name); @@ -3697,7 +3667,8 @@ int omap_hwmod_init_module(struct device *dev, return error; return omap_hwmod_allocate_module(dev, oh, data, sysc_fields, - rev_offs, sysc_offs, syss_offs, + cookie->clkdm, rev_offs, + sysc_offs, syss_offs, sysc_flags, idlemodes); } diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index a2ecc5e69abb..b09cc4e8d240 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -29,6 +29,7 @@ #include #include +#include "clockdomain.h" #include "common.h" #include "common-board-devices.h" #include "control.h" @@ -463,6 +464,62 @@ static void __init dra7x_evm_mmc_quirk(void) } #endif +static struct clockdomain *ti_sysc_find_one_clockdomain(struct clk *clk) +{ + struct clockdomain *clkdm = NULL; + struct clk_hw_omap *hwclk; + + hwclk = to_clk_hw_omap(__clk_get_hw(clk)); + if (hwclk && hwclk->clkdm_name) + clkdm = clkdm_lookup(hwclk->clkdm_name); + + return clkdm; +} + +/** + * ti_sysc_clkdm_init - find clockdomain based on clock + * @fck: device functional clock + * @ick: device interface clock + * @dev: struct device + * + * Populate clockdomain based on clock. It is needed for + * clkdm_deny_idle() and clkdm_allow_idle() for blocking clockdomain + * clockdomain idle during reset, enable and idle. + * + * Note that we assume interconnect driver manages the clocks + * and do not need to populate oh->_clk for dynamically + * allocated modules. + */ +static int ti_sysc_clkdm_init(struct device *dev, + struct clk *fck, struct clk *ick, + struct ti_sysc_cookie *cookie) +{ + if (fck) + cookie->clkdm = ti_sysc_find_one_clockdomain(fck); + if (cookie->clkdm) + return 0; + if (ick) + cookie->clkdm = ti_sysc_find_one_clockdomain(ick); + if (cookie->clkdm) + return 0; + + return -ENODEV; +} + +static void ti_sysc_clkdm_deny_idle(struct device *dev, + const struct ti_sysc_cookie *cookie) +{ + if (cookie->clkdm) + clkdm_deny_idle(cookie->clkdm); +} + +static void ti_sysc_clkdm_allow_idle(struct device *dev, + const struct ti_sysc_cookie *cookie) +{ + if (cookie->clkdm) + clkdm_allow_idle(cookie->clkdm); +} + static int ti_sysc_enable_module(struct device *dev, const struct ti_sysc_cookie *cookie) { @@ -494,6 +551,9 @@ static struct of_dev_auxdata omap_auxdata_lookup[]; static struct ti_sysc_platform_data ti_sysc_pdata = { .auxdata = omap_auxdata_lookup, + .init_clockdomain = ti_sysc_clkdm_init, + .clkdm_deny_idle = ti_sysc_clkdm_deny_idle, + .clkdm_allow_idle = ti_sysc_clkdm_allow_idle, .init_module = omap_hwmod_init_module, .enable_module = ti_sysc_enable_module, .idle_module = ti_sysc_idle_module, diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index b72741668c92..e86f7850206a 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -422,6 +422,30 @@ static void sysc_disable_opt_clocks(struct sysc *ddata) } } +static void sysc_clkdm_deny_idle(struct sysc *ddata) +{ + struct ti_sysc_platform_data *pdata; + + if (ddata->legacy_mode) + return; + + pdata = dev_get_platdata(ddata->dev); + if (pdata && pdata->clkdm_deny_idle) + pdata->clkdm_deny_idle(ddata->dev, &ddata->cookie); +} + +static void sysc_clkdm_allow_idle(struct sysc *ddata) +{ + struct ti_sysc_platform_data *pdata; + + if (ddata->legacy_mode) + return; + + pdata = dev_get_platdata(ddata->dev); + if (pdata && pdata->clkdm_allow_idle) + pdata->clkdm_allow_idle(ddata->dev, &ddata->cookie); +} + /** * sysc_init_resets - init rstctrl reset line if configured * @ddata: device driver data @@ -795,6 +819,7 @@ static void sysc_show_registers(struct sysc *ddata) #define SYSC_IDLE_MASK (SYSC_NR_IDLEMODES - 1) +/* Caller needs to manage sysc_clkdm_deny_idle() and sysc_clkdm_allow_idle() */ static int sysc_enable_module(struct device *dev) { struct sysc *ddata; @@ -805,11 +830,6 @@ static int sysc_enable_module(struct device *dev) if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV) return 0; - /* - * TODO: Need to prevent clockdomain autoidle? - * See clkdm_deny_idle() in arch/mach-omap2/omap_hwmod.c - */ - regbits = ddata->cap->regbits; reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); @@ -861,6 +881,7 @@ static int sysc_best_idle_mode(u32 idlemodes, u32 *best_mode) return 0; } +/* Caller needs to manage sysc_clkdm_deny_idle() and sysc_clkdm_allow_idle() */ static int sysc_disable_module(struct device *dev) { struct sysc *ddata; @@ -872,11 +893,6 @@ static int sysc_disable_module(struct device *dev) if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV) return 0; - /* - * TODO: Need to prevent clockdomain autoidle? - * See clkdm_deny_idle() in arch/mach-omap2/omap_hwmod.c - */ - regbits = ddata->cap->regbits; reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); @@ -966,14 +982,16 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev) if (!ddata->enabled) return 0; + sysc_clkdm_deny_idle(ddata); + if (ddata->legacy_mode) { error = sysc_runtime_suspend_legacy(dev, ddata); if (error) - return error; + goto err_allow_idle; } else { error = sysc_disable_module(dev); if (error) - return error; + goto err_allow_idle; } sysc_disable_main_clocks(ddata); @@ -983,6 +1001,9 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev) ddata->enabled = false; +err_allow_idle: + sysc_clkdm_allow_idle(ddata); + return error; } @@ -996,10 +1017,12 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev) if (ddata->enabled) return 0; + sysc_clkdm_deny_idle(ddata); + if (sysc_opt_clks_needed(ddata)) { error = sysc_enable_opt_clocks(ddata); if (error) - return error; + goto err_allow_idle; } error = sysc_enable_main_clocks(ddata); @@ -1018,6 +1041,8 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev) ddata->enabled = true; + sysc_clkdm_allow_idle(ddata); + return 0; err_main_clocks: @@ -1025,6 +1050,8 @@ err_main_clocks: err_opt_clocks: if (sysc_opt_clks_needed(ddata)) sysc_disable_opt_clocks(ddata); +err_allow_idle: + sysc_clkdm_allow_idle(ddata); return error; } @@ -1245,6 +1272,33 @@ static void sysc_init_revision_quirks(struct sysc *ddata) } } +static int sysc_clockdomain_init(struct sysc *ddata) +{ + struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev); + struct clk *fck = NULL, *ick = NULL; + int error; + + if (!pdata || !pdata->init_clockdomain) + return 0; + + switch (ddata->nr_clocks) { + case 2: + ick = ddata->clocks[SYSC_ICK]; + /* fallthrough */ + case 1: + fck = ddata->clocks[SYSC_FCK]; + break; + case 0: + return 0; + } + + error = pdata->init_clockdomain(ddata->dev, fck, ick, &ddata->cookie); + if (!error || error == -ENODEV) + return 0; + + return error; +} + /* * Note that pdata->init_module() typically does a reset first. After * pdata->init_module() is done, PM runtime can be used for the interconnect @@ -1255,7 +1309,7 @@ static int sysc_legacy_init(struct sysc *ddata) struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev); int error; - if (!ddata->legacy_mode || !pdata || !pdata->init_module) + if (!pdata || !pdata->init_module) return 0; error = pdata->init_module(ddata->dev, ddata->mdata, &ddata->cookie); @@ -1347,7 +1401,13 @@ static int sysc_init_module(struct sysc *ddata) (SYSC_QUIRK_NO_IDLE | SYSC_QUIRK_NO_IDLE_ON_INIT)) manage_clocks = false; + error = sysc_clockdomain_init(ddata); + if (error) + return error; + if (manage_clocks) { + sysc_clkdm_deny_idle(ddata); + error = sysc_enable_opt_clocks(ddata); if (error) return error; @@ -1360,20 +1420,33 @@ static int sysc_init_module(struct sysc *ddata) ddata->revision = sysc_read_revision(ddata); sysc_init_revision_quirks(ddata); - error = sysc_legacy_init(ddata); - if (error) - goto err_main_clocks; + if (ddata->legacy_mode) { + error = sysc_legacy_init(ddata); + if (error) + goto err_main_clocks; + } + + if (!ddata->legacy_mode && manage_clocks) { + error = sysc_enable_module(ddata->dev); + if (error) + goto err_main_clocks; + } error = sysc_reset(ddata); if (error) dev_err(ddata->dev, "Reset failed with %d\n", error); + if (!ddata->legacy_mode && manage_clocks) + sysc_disable_module(ddata->dev); + err_main_clocks: if (manage_clocks) sysc_disable_main_clocks(ddata); err_opt_clocks: - if (manage_clocks) + if (manage_clocks) { sysc_disable_opt_clocks(ddata); + sysc_clkdm_allow_idle(ddata); + } return error; } @@ -2012,20 +2085,22 @@ static int sysc_init_pdata(struct sysc *ddata) struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev); struct ti_sysc_module_data *mdata; - if (!pdata || !ddata->legacy_mode) + if (!pdata) return 0; mdata = devm_kzalloc(ddata->dev, sizeof(*mdata), GFP_KERNEL); if (!mdata) return -ENOMEM; - mdata->name = ddata->legacy_mode; - mdata->module_pa = ddata->module_pa; - mdata->module_size = ddata->module_size; - mdata->offsets = ddata->offsets; - mdata->nr_offsets = SYSC_MAX_REGS; - mdata->cap = ddata->cap; - mdata->cfg = &ddata->cfg; + if (ddata->legacy_mode) { + mdata->name = ddata->legacy_mode; + mdata->module_pa = ddata->module_pa; + mdata->module_size = ddata->module_size; + mdata->offsets = ddata->offsets; + mdata->nr_offsets = SYSC_MAX_REGS; + mdata->cap = ddata->cap; + mdata->cfg = &ddata->cfg; + } ddata->mdata = mdata; diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 9256c0305968..6626fd31e309 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -19,6 +19,7 @@ enum ti_sysc_module_type { struct ti_sysc_cookie { void *data; + void *clkdm; }; /** @@ -125,9 +126,16 @@ struct ti_sysc_module_data { }; struct device; +struct clk; struct ti_sysc_platform_data { struct of_dev_auxdata *auxdata; + int (*init_clockdomain)(struct device *dev, struct clk *fck, + struct clk *ick, struct ti_sysc_cookie *cookie); + void (*clkdm_deny_idle)(struct device *dev, + const struct ti_sysc_cookie *cookie); + void (*clkdm_allow_idle)(struct device *dev, + const struct ti_sysc_cookie *cookie); int (*init_module)(struct device *dev, const struct ti_sysc_module_data *data, struct ti_sysc_cookie *cookie); -- cgit v1.2.3 From e0db94fe87dacd72be0699adcc29e321db7f1689 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 27 May 2019 04:51:53 -0700 Subject: bus: ti-sysc: Make OCP reset work for sysstatus and sysconfig reset bits We've had minimal OCP softreset support in ti-sysc interconnect target module driver only used for MCAN driver so far. But it turns out that MCAN has the sysstatus register resetdone bit inverted compared to most other modules. Let's make OCP softreset work for other typical cases with reset status in sysstatus or sysconfig register so we can use the new functions for sysc_enable_module() and sysc_disable_module() without "ti,hwmods" property in the following patches. Tested-by: Keerthy Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 72 ++++++++++++++++++++++++++--------- include/linux/platform_data/ti-sysc.h | 1 + 2 files changed, 55 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index f00997eea207..f4a048430cd1 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -153,6 +153,26 @@ static u32 sysc_read_revision(struct sysc *ddata) return sysc_read(ddata, offset); } +static u32 sysc_read_sysconfig(struct sysc *ddata) +{ + int offset = ddata->offsets[SYSC_SYSCONFIG]; + + if (offset < 0) + return 0; + + return sysc_read(ddata, offset); +} + +static u32 sysc_read_sysstatus(struct sysc *ddata) +{ + int offset = ddata->offsets[SYSC_SYSSTATUS]; + + if (offset < 0) + return 0; + + return sysc_read(ddata, offset); +} + static int sysc_add_named_clock_from_child(struct sysc *ddata, const char *name, const char *optfck_name) @@ -1369,34 +1389,49 @@ static int sysc_rstctrl_reset_deassert(struct sysc *ddata, bool reset) return reset_control_deassert(ddata->rsts); } +/* + * Note that the caller must ensure the interconnect target module is enabled + * before calling reset. Otherwise reset will not complete. + */ static int sysc_reset(struct sysc *ddata) { - int offset = ddata->offsets[SYSC_SYSCONFIG]; - int val; + int sysc_offset, syss_offset, sysc_val, rstval, quirks, error = 0; + u32 sysc_mask, syss_done; + + sysc_offset = ddata->offsets[SYSC_SYSCONFIG]; + syss_offset = ddata->offsets[SYSC_SYSSTATUS]; + quirks = ddata->cfg.quirks; - if (ddata->legacy_mode || offset < 0 || + if (ddata->legacy_mode || sysc_offset < 0 || + ddata->cap->regbits->srst_shift < 0 || ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) return 0; - /* - * Currently only support reset status in sysstatus. - * Warn and return error in all other cases - */ - if (!ddata->cfg.syss_mask) { - dev_err(ddata->dev, "No ti,syss-mask. Reset failed\n"); - return -EINVAL; - } + sysc_mask = BIT(ddata->cap->regbits->srst_shift); - val = sysc_read(ddata, offset); - val |= (0x1 << ddata->cap->regbits->srst_shift); - sysc_write(ddata, offset, val); + if (ddata->cfg.quirks & SYSS_QUIRK_RESETDONE_INVERTED) + syss_done = 0; + else + syss_done = ddata->cfg.syss_mask; + + sysc_val = sysc_read_sysconfig(ddata); + sysc_val |= sysc_mask; + sysc_write(ddata, sysc_offset, sysc_val); /* Poll on reset status */ - offset = ddata->offsets[SYSC_SYSSTATUS]; + if (syss_offset >= 0) { + error = readx_poll_timeout(sysc_read_sysstatus, ddata, rstval, + (rstval & ddata->cfg.syss_mask) == + syss_done, + 100, MAX_MODULE_SOFTRESET_WAIT); + + } else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) { + error = readx_poll_timeout(sysc_read_sysconfig, ddata, rstval, + !(rstval & sysc_mask), + 100, MAX_MODULE_SOFTRESET_WAIT); + } - return readl_poll_timeout(ddata->module_va + offset, val, - (val & ddata->cfg.syss_mask) == 0x0, - 100, MAX_MODULE_SOFTRESET_WAIT); + return error; } /* @@ -2099,6 +2134,7 @@ static const struct sysc_capabilities sysc_dra7_mcan = { .type = TI_SYSC_DRA7_MCAN, .sysc_mask = SYSC_DRA7_MCAN_ENAWAKEUP | SYSC_OMAP4_SOFTRESET, .regbits = &sysc_regbits_dra7_mcan, + .mod_quirks = SYSS_QUIRK_RESETDONE_INVERTED, }; static int sysc_init_pdata(struct sysc *ddata) diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 6626fd31e309..8822e99ff813 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -47,6 +47,7 @@ struct sysc_regbits { s8 emufree_shift; }; +#define SYSS_QUIRK_RESETDONE_INVERTED BIT(14) #define SYSC_QUIRK_SWSUP_MSTANDBY BIT(13) #define SYSC_QUIRK_SWSUP_SIDLE_ACT BIT(12) #define SYSC_QUIRK_SWSUP_SIDLE BIT(11) -- cgit v1.2.3 From 0cb93b1503c19f19966402c3ed841626ac9db266 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 13 May 2019 15:50:10 +0530 Subject: dt-bindings: power: Add rpm power domain bindings for qcs404 Add RPM power domain bindings for the qcs404 family of SoC Reviewed-by: Rob Herring Reviewed-by: Jeffrey Hugo Reviewed-by: Vinod Koul Signed-off-by: Bjorn Andersson [sibis: Add supported rpmpd states for qcs404] Signed-off-by: Sibi Sankar Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- .../devicetree/bindings/power/qcom,rpmpd.txt | 1 + include/dt-bindings/power/qcom-rpmpd.h | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'include') diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt index 980e5413d18f..172ccf940c5c 100644 --- a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt +++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt @@ -6,6 +6,7 @@ which then translates it into a corresponding voltage on a rail Required Properties: - compatible: Should be one of the following * qcom,msm8996-rpmpd: RPM Power domain for the msm8996 family of SoC + * qcom,qcs404-rpmpd: RPM Power domain for the qcs404 family of SoC * qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC - #power-domain-cells: number of cells in Power domain specifier must be 1. diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h index 87d9c6611682..450378662944 100644 --- a/include/dt-bindings/power/qcom-rpmpd.h +++ b/include/dt-bindings/power/qcom-rpmpd.h @@ -36,4 +36,26 @@ #define MSM8996_VDDSSCX 5 #define MSM8996_VDDSSCX_VFC 6 +/* QCS404 Power Domains */ +#define QCS404_VDDMX 0 +#define QCS404_VDDMX_AO 1 +#define QCS404_VDDMX_VFL 2 +#define QCS404_LPICX 3 +#define QCS404_LPICX_VFL 4 +#define QCS404_LPIMX 5 +#define QCS404_LPIMX_VFL 6 + +/* RPM SMD Power Domain performance levels */ +#define RPM_SMD_LEVEL_RETENTION 16 +#define RPM_SMD_LEVEL_RETENTION_PLUS 32 +#define RPM_SMD_LEVEL_MIN_SVS 48 +#define RPM_SMD_LEVEL_LOW_SVS 64 +#define RPM_SMD_LEVEL_SVS 128 +#define RPM_SMD_LEVEL_SVS_PLUS 192 +#define RPM_SMD_LEVEL_NOM 256 +#define RPM_SMD_LEVEL_NOM_PLUS 320 +#define RPM_SMD_LEVEL_TURBO 384 +#define RPM_SMD_LEVEL_TURBO_NO_CPR 416 +#define RPM_SMD_LEVEL_BINNING 512 + #endif -- cgit v1.2.3 From dec9a05a147e4988e1f743c0d0a1389a0552e322 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 13 May 2019 15:50:13 +0530 Subject: dt-bindings: power: Add rpm power domain bindings for msm8998 Add RPM power domain bindings for the msm8998 family of SoC Reviewed-by: Rob Herring Reviewed-by: Jeffrey Hugo Reviewed-by: Vinod Koul Signed-off-by: Sibi Sankar Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- Documentation/devicetree/bindings/power/qcom,rpmpd.txt | 1 + include/dt-bindings/power/qcom-rpmpd.h | 12 ++++++++++++ 2 files changed, 13 insertions(+) (limited to 'include') diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt index 172ccf940c5c..eb35b22f9e23 100644 --- a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt +++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt @@ -6,6 +6,7 @@ which then translates it into a corresponding voltage on a rail Required Properties: - compatible: Should be one of the following * qcom,msm8996-rpmpd: RPM Power domain for the msm8996 family of SoC + * qcom,msm8998-rpmpd: RPM Power domain for the msm8998 family of SoC * qcom,qcs404-rpmpd: RPM Power domain for the qcs404 family of SoC * qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC - #power-domain-cells: number of cells in Power domain specifier diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h index 450378662944..93e36d011527 100644 --- a/include/dt-bindings/power/qcom-rpmpd.h +++ b/include/dt-bindings/power/qcom-rpmpd.h @@ -36,6 +36,18 @@ #define MSM8996_VDDSSCX 5 #define MSM8996_VDDSSCX_VFC 6 +/* MSM8998 Power Domain Indexes */ +#define MSM8998_VDDCX 0 +#define MSM8998_VDDCX_AO 1 +#define MSM8998_VDDCX_VFL 2 +#define MSM8998_VDDMX 3 +#define MSM8998_VDDMX_AO 4 +#define MSM8998_VDDMX_VFL 5 +#define MSM8998_SSCCX 6 +#define MSM8998_SSCCX_VFL 7 +#define MSM8998_SSCMX 8 +#define MSM8998_SSCMX_VFL 9 + /* QCS404 Power Domains */ #define QCS404_VDDMX 0 #define QCS404_VDDMX_AO 1 -- cgit v1.2.3 From 4e23be473e3063a9d3bc06bb0aee89885fffab0e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 10 Jun 2019 04:48:05 -0700 Subject: bus: ti-sysc: Add support for module specific reset quirks Some older interconnect target modules need module internal clock toggling quirks to reset properly. We've been doing this in the platform code earlier, but need to be able to it directly in the ti-sysc driver when we no longer rely on on the platform code. Let's add reset handling for 1-wire, i2c and watchdog. Later on we can add more modules like msdi and dss as they get tested. For dra7 pcie, we should be able to just use the rstctrl reset driver when available. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 129 ++++++++++++++++++++++++++++++++-- include/linux/platform_data/ti-sysc.h | 3 + 2 files changed, 127 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index a366ae548ec9..e6deabd8305d 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -71,6 +71,9 @@ static const char * const clock_names[SYSC_MAX_CLOCKS] = { * @name: name if available * @revision: interconnect target module revision * @needs_resume: runtime resume needed on resume from suspend + * @clk_enable_quirk: module specific clock enable quirk + * @clk_disable_quirk: module specific clock disable quirk + * @reset_done_quirk: module specific reset done quirk */ struct sysc { struct device *dev; @@ -94,6 +97,9 @@ struct sysc { unsigned int child_needs_resume:1; unsigned int disable_on_idle:1; struct delayed_work idle_work; + void (*clk_enable_quirk)(struct sysc *sysc); + void (*clk_disable_quirk)(struct sysc *sysc); + void (*reset_done_quirk)(struct sysc *sysc); }; static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np, @@ -760,8 +766,11 @@ static int sysc_ioremap(struct sysc *ddata) ddata->offsets[SYSC_SYSCONFIG], ddata->offsets[SYSC_SYSSTATUS]); + if (size < SZ_1K) + size = SZ_1K; + if ((size + sizeof(u32)) > ddata->module_size) - return -EINVAL; + size = ddata->module_size; } ddata->module_va = devm_ioremap(ddata->dev, @@ -1234,6 +1243,22 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK_EXT_OPT_CLOCK | SYSC_QUIRK_NO_RESET_ON_INIT | SYSC_QUIRK_SWSUP_SIDLE), + /* Quirks that need to be set based on detected module */ + SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, + SYSC_MODULE_QUIRK_HDQ1W), + SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff, + SYSC_MODULE_QUIRK_HDQ1W), + SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000036, 0x000000ff, + SYSC_MODULE_QUIRK_I2C), + SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x0000003c, 0x000000ff, + SYSC_MODULE_QUIRK_I2C), + SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000040, 0x000000ff, + SYSC_MODULE_QUIRK_I2C), + SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0, + SYSC_MODULE_QUIRK_I2C), + SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, + SYSC_MODULE_QUIRK_WDT), + #ifdef DEBUG SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0), SYSC_QUIRK("atl", 0, 0, -1, -1, 0x0a070100, 0xffffffff, 0), @@ -1247,11 +1272,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0), SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0), SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0), - SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, 0), - SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff, 0), SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0), SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0), - SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0, 0), SYSC_QUIRK("lcdc", 0, 0, 0x54, -1, 0x4f201000, 0xffffffff, 0), SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0), SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44307b02, 0xffffffff, 0), @@ -1287,7 +1309,6 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -1, 0x50700101, 0xffffffff, 0), SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050, 0xffffffff, 0), - SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, 0), SYSC_QUIRK("vfpe", 0, 0, 0x104, -1, 0x4d001200, 0xffffffff, 0), #endif }; @@ -1360,6 +1381,94 @@ static void sysc_init_revision_quirks(struct sysc *ddata) } } +/* 1-wire needs module's internal clocks enabled for reset */ +static void sysc_clk_enable_quirk_hdq1w(struct sysc *ddata) +{ + int offset = 0x0c; /* HDQ_CTRL_STATUS */ + u16 val; + + val = sysc_read(ddata, offset); + val |= BIT(5); + sysc_write(ddata, offset, val); +} + +/* I2C needs extra enable bit toggling for reset */ +static void sysc_clk_quirk_i2c(struct sysc *ddata, bool enable) +{ + int offset; + u16 val; + + /* I2C_CON, omap2/3 is different from omap4 and later */ + if ((ddata->revision & 0xffffff00) == 0x001f0000) + offset = 0x24; + else + offset = 0xa4; + + /* I2C_EN */ + val = sysc_read(ddata, offset); + if (enable) + val |= BIT(15); + else + val &= ~BIT(15); + sysc_write(ddata, offset, val); +} + +static void sysc_clk_enable_quirk_i2c(struct sysc *ddata) +{ + sysc_clk_quirk_i2c(ddata, true); +} + +static void sysc_clk_disable_quirk_i2c(struct sysc *ddata) +{ + sysc_clk_quirk_i2c(ddata, false); +} + +/* Watchdog timer needs a disable sequence after reset */ +static void sysc_reset_done_quirk_wdt(struct sysc *ddata) +{ + int wps, spr, error; + u32 val; + + wps = 0x34; + spr = 0x48; + + sysc_write(ddata, spr, 0xaaaa); + error = readl_poll_timeout(ddata->module_va + wps, val, + !(val & 0x10), 100, + MAX_MODULE_SOFTRESET_WAIT); + if (error) + dev_warn(ddata->dev, "wdt disable spr failed\n"); + + sysc_write(ddata, wps, 0x5555); + error = readl_poll_timeout(ddata->module_va + wps, val, + !(val & 0x10), 100, + MAX_MODULE_SOFTRESET_WAIT); + if (error) + dev_warn(ddata->dev, "wdt disable wps failed\n"); +} + +static void sysc_init_module_quirks(struct sysc *ddata) +{ + if (ddata->legacy_mode || !ddata->name) + return; + + if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_HDQ1W) { + ddata->clk_enable_quirk = sysc_clk_enable_quirk_hdq1w; + + return; + } + + if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_I2C) { + ddata->clk_enable_quirk = sysc_clk_enable_quirk_i2c; + ddata->clk_disable_quirk = sysc_clk_disable_quirk_i2c; + + return; + } + + if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_WDT) + ddata->reset_done_quirk = sysc_reset_done_quirk_wdt; +} + static int sysc_clockdomain_init(struct sysc *ddata) { struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev); @@ -1468,10 +1577,16 @@ static int sysc_reset(struct sysc *ddata) else syss_done = ddata->cfg.syss_mask; + if (ddata->clk_disable_quirk) + ddata->clk_disable_quirk(ddata); + sysc_val = sysc_read_sysconfig(ddata); sysc_val |= sysc_mask; sysc_write(ddata, sysc_offset, sysc_val); + if (ddata->clk_enable_quirk) + ddata->clk_enable_quirk(ddata); + /* Poll on reset status */ if (syss_offset >= 0) { error = readx_poll_timeout(sysc_read_sysstatus, ddata, rstval, @@ -1485,6 +1600,9 @@ static int sysc_reset(struct sysc *ddata) 100, MAX_MODULE_SOFTRESET_WAIT); } + if (ddata->reset_done_quirk) + ddata->reset_done_quirk(ddata); + return error; } @@ -1531,6 +1649,7 @@ static int sysc_init_module(struct sysc *ddata) ddata->revision = sysc_read_revision(ddata); sysc_init_revision_quirks(ddata); + sysc_init_module_quirks(ddata); if (ddata->legacy_mode) { error = sysc_legacy_init(ddata); diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 8822e99ff813..0c587d4fc718 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -47,6 +47,9 @@ struct sysc_regbits { s8 emufree_shift; }; +#define SYSC_MODULE_QUIRK_HDQ1W BIT(17) +#define SYSC_MODULE_QUIRK_I2C BIT(16) +#define SYSC_MODULE_QUIRK_WDT BIT(15) #define SYSS_QUIRK_RESETDONE_INVERTED BIT(14) #define SYSC_QUIRK_SWSUP_MSTANDBY BIT(13) #define SYSC_QUIRK_SWSUP_SIDLE_ACT BIT(12) -- cgit v1.2.3 From 8ad2b4b371bcfe7069ee28ad18d722e1240a0a97 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 11 Jun 2019 21:45:33 -0700 Subject: dt-bindings: soc: qcom: Add AOSS QMP binding Add binding for the QMP based side-channel communication mechanism to the AOSS, which is used to control resources not exposed through the RPMh interface. Reviewed-by: Rob Herring Reviewed-by: Vinod Koul Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt | 81 ++++++++++++++++++++++ include/dt-bindings/power/qcom-aoss-qmp.h | 14 ++++ 2 files changed, 95 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt create mode 100644 include/dt-bindings/power/qcom-aoss-qmp.h (limited to 'include') diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt new file mode 100644 index 000000000000..954ffee0a9c4 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.txt @@ -0,0 +1,81 @@ +Qualcomm Always-On Subsystem side channel binding + +This binding describes the hardware component responsible for side channel +requests to the always-on subsystem (AOSS), used for certain power management +requests that is not handled by the standard RPMh interface. Each client in the +SoC has it's own block of message RAM and IRQ for communication with the AOSS. +The protocol used to communicate in the message RAM is known as Qualcomm +Messaging Protocol (QMP) + +The AOSS side channel exposes control over a set of resources, used to control +a set of debug related clocks and to affect the low power state of resources +related to the secondary subsystems. These resources are exposed as a set of +power-domains. + +- compatible: + Usage: required + Value type: + Definition: must be "qcom,sdm845-aoss-qmp" + +- reg: + Usage: required + Value type: + Definition: the base address and size of the message RAM for this + client's communication with the AOSS + +- interrupts: + Usage: required + Value type: + Definition: should specify the AOSS message IRQ for this client + +- mboxes: + Usage: required + Value type: + Definition: reference to the mailbox representing the outgoing doorbell + in APCS for this client, as described in mailbox/mailbox.txt + +- #clock-cells: + Usage: optional + Value type: + Definition: must be 0 + The single clock represents the QDSS clock. + +- #power-domain-cells: + Usage: optional + Value type: + Definition: must be 1 + The provided power-domains are: + CDSP state (0), LPASS state (1), modem state (2), SLPI + state (3), SPSS state (4) and Venus state (5). + += SUBNODES +The AOSS side channel also provides the controls for three cooling devices, +these are expressed as subnodes of the QMP node. The name of the node is used +to identify the resource and must therefor be "cx", "mx" or "ebi". + +- #cooling-cells: + Usage: optional + Value type: + Definition: must be 2 + += EXAMPLE + +The following example represents the AOSS side-channel message RAM and the +mechanism exposing the power-domains, as found in SDM845. + + aoss_qmp: qmp@c300000 { + compatible = "qcom,sdm845-aoss-qmp"; + reg = <0x0c300000 0x100000>; + interrupts = ; + mboxes = <&apss_shared 0>; + + #power-domain-cells = <1>; + + cx_cdev: cx { + #cooling-cells = <2>; + }; + + mx_cdev: mx { + #cooling-cells = <2>; + }; + }; diff --git a/include/dt-bindings/power/qcom-aoss-qmp.h b/include/dt-bindings/power/qcom-aoss-qmp.h new file mode 100644 index 000000000000..ec336d31dee4 --- /dev/null +++ b/include/dt-bindings/power/qcom-aoss-qmp.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2018, Linaro Ltd. */ + +#ifndef __DT_BINDINGS_POWER_QCOM_AOSS_QMP_H +#define __DT_BINDINGS_POWER_QCOM_AOSS_QMP_H + +#define AOSS_QMP_LS_CDSP 0 +#define AOSS_QMP_LS_LPASS 1 +#define AOSS_QMP_LS_MODEM 2 +#define AOSS_QMP_LS_SLPI 3 +#define AOSS_QMP_LS_SPSS 4 +#define AOSS_QMP_LS_VENUS 5 + +#endif -- cgit v1.2.3 From 0b673b6486998061b0489b09447ebe8452da0146 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 8 May 2019 11:46:34 -0700 Subject: firmware: arm_scmi: fetch and store sensor scale In preparation for dealing with scales within the SCMI HWMON driver, fetch and store the sensor unit scale into the scmi_sensor_info structure. In order to simplify computations for upper layer, take care of sign extending the scale to a full 8-bit signed value. Reviewed-by: Guenter Roeck Signed-off-by: Florian Fainelli [sudeep.holla: update bitfield values as per specification] Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/sensors.c | 6 ++++++ include/linux/scmi_protocol.h | 1 + 2 files changed, 7 insertions(+) (limited to 'include') diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index c00287b5f2c2..0e94ab56f679 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -34,6 +34,8 @@ struct scmi_msg_resp_sensor_description { __le32 attributes_high; #define SENSOR_TYPE(x) ((x) & 0xff) #define SENSOR_SCALE(x) (((x) >> 11) & 0x1f) +#define SENSOR_SCALE_SIGN BIT(4) +#define SENSOR_SCALE_EXTEND GENMASK(7, 5) #define SENSOR_UPDATE_SCALE(x) (((x) >> 22) & 0x1f) #define SENSOR_UPDATE_BASE(x) (((x) >> 27) & 0x1f) u8 name[SCMI_MAX_STR_SIZE]; @@ -140,6 +142,10 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle, s = &si->sensors[desc_index + cnt]; s->id = le32_to_cpu(buf->desc[cnt].id); s->type = SENSOR_TYPE(attrh); + s->scale = SENSOR_SCALE(attrh); + /* Sign extend to a full s8 */ + if (s->scale & SENSOR_SCALE_SIGN) + s->scale |= SENSOR_SCALE_EXTEND; strlcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE); } diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 3105055c00a7..9ff2e9357e9a 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -144,6 +144,7 @@ struct scmi_power_ops { struct scmi_sensor_info { u32 id; u8 type; + s8 scale; char name[SCMI_MAX_STR_SIZE]; }; -- cgit v1.2.3 From 68608b5e5063dd12942f1118286c6f595d0c4a05 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 10 Jun 2019 12:18:56 +0300 Subject: firmware: ti_sci: Add resource management APIs for ringacc, psi-l and udma Configuration of NAVSS resource, like rings, UDMAP channels, flows and PSI-L thread management need to be done via TISCI. Add the needed structures and functions for NAVSS resource configuration of the following: Rings from Ring Accelerator PSI-L thread management UDMAP tchan, rchan and rflow configuration. Signed-off-by: Peter Ujfalusi Reviewed-by: Lokesh Vutla Signed-off-by: Tero Kristo Signed-off-by: Santosh Shilimkar --- drivers/firmware/ti_sci.c | 488 ++++++++++++++++++++++++ drivers/firmware/ti_sci.h | 675 +++++++++++++++++++++++++++++++++ include/linux/soc/ti/ti_sci_protocol.h | 215 +++++++++++ 3 files changed, 1378 insertions(+) (limited to 'include') diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 36ce11a67235..02fa196428d8 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -2004,6 +2004,481 @@ static int ti_sci_cmd_free_event_map(const struct ti_sci_handle *handle, ia_id, vint, global_event, vint_status_bit, 0); } +/** + * ti_sci_cmd_ring_config() - configure RA ring + * @handle: Pointer to TI SCI handle. + * @valid_params: Bitfield defining validity of ring configuration + * parameters + * @nav_id: Device ID of Navigator Subsystem from which the ring is + * allocated + * @index: Ring index + * @addr_lo: The ring base address lo 32 bits + * @addr_hi: The ring base address hi 32 bits + * @count: Number of ring elements + * @mode: The mode of the ring + * @size: The ring element size. + * @order_id: Specifies the ring's bus order ID + * + * Return: 0 if all went well, else returns appropriate error value. + * + * See @ti_sci_msg_rm_ring_cfg_req for more info. + */ +static int ti_sci_cmd_ring_config(const struct ti_sci_handle *handle, + u32 valid_params, u16 nav_id, u16 index, + u32 addr_lo, u32 addr_hi, u32 count, + u8 mode, u8 size, u8 order_id) +{ + struct ti_sci_msg_rm_ring_cfg_req *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + struct device *dev; + int ret = 0; + + if (IS_ERR_OR_NULL(handle)) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_RM_RING_CFG, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "RM_RA:Message config failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_rm_ring_cfg_req *)xfer->xfer_buf; + req->valid_params = valid_params; + req->nav_id = nav_id; + req->index = index; + req->addr_lo = addr_lo; + req->addr_hi = addr_hi; + req->count = count; + req->mode = mode; + req->size = size; + req->order_id = order_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "RM_RA:Mbox config send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + dev_dbg(info->dev, "RM_RA:config ring %u ret:%d\n", index, ret); + return ret; +} + +/** + * ti_sci_cmd_ring_get_config() - get RA ring configuration + * @handle: Pointer to TI SCI handle. + * @nav_id: Device ID of Navigator Subsystem from which the ring is + * allocated + * @index: Ring index + * @addr_lo: Returns ring's base address lo 32 bits + * @addr_hi: Returns ring's base address hi 32 bits + * @count: Returns number of ring elements + * @mode: Returns mode of the ring + * @size: Returns ring element size + * @order_id: Returns ring's bus order ID + * + * Return: 0 if all went well, else returns appropriate error value. + * + * See @ti_sci_msg_rm_ring_get_cfg_req for more info. + */ +static int ti_sci_cmd_ring_get_config(const struct ti_sci_handle *handle, + u32 nav_id, u32 index, u8 *mode, + u32 *addr_lo, u32 *addr_hi, + u32 *count, u8 *size, u8 *order_id) +{ + struct ti_sci_msg_rm_ring_get_cfg_resp *resp; + struct ti_sci_msg_rm_ring_get_cfg_req *req; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + struct device *dev; + int ret = 0; + + if (IS_ERR_OR_NULL(handle)) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_RM_RING_GET_CFG, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, + "RM_RA:Message get config failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_rm_ring_get_cfg_req *)xfer->xfer_buf; + req->nav_id = nav_id; + req->index = index; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "RM_RA:Mbox get config send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_rm_ring_get_cfg_resp *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) { + ret = -ENODEV; + } else { + if (mode) + *mode = resp->mode; + if (addr_lo) + *addr_lo = resp->addr_lo; + if (addr_hi) + *addr_hi = resp->addr_hi; + if (count) + *count = resp->count; + if (size) + *size = resp->size; + if (order_id) + *order_id = resp->order_id; + }; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + dev_dbg(info->dev, "RM_RA:get config ring %u ret:%d\n", index, ret); + return ret; +} + +/** + * ti_sci_cmd_rm_psil_pair() - Pair PSI-L source to destination thread + * @handle: Pointer to TI SCI handle. + * @nav_id: Device ID of Navigator Subsystem which should be used for + * pairing + * @src_thread: Source PSI-L thread ID + * @dst_thread: Destination PSI-L thread ID + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_rm_psil_pair(const struct ti_sci_handle *handle, + u32 nav_id, u32 src_thread, u32 dst_thread) +{ + struct ti_sci_msg_psil_pair *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_RM_PSIL_PAIR, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "RM_PSIL:Message reconfig failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_psil_pair *)xfer->xfer_buf; + req->nav_id = nav_id; + req->src_thread = src_thread; + req->dst_thread = dst_thread; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "RM_PSIL:Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_rm_psil_unpair() - Unpair PSI-L source from destination thread + * @handle: Pointer to TI SCI handle. + * @nav_id: Device ID of Navigator Subsystem which should be used for + * unpairing + * @src_thread: Source PSI-L thread ID + * @dst_thread: Destination PSI-L thread ID + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_rm_psil_unpair(const struct ti_sci_handle *handle, + u32 nav_id, u32 src_thread, u32 dst_thread) +{ + struct ti_sci_msg_psil_unpair *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_RM_PSIL_UNPAIR, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "RM_PSIL:Message reconfig failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_psil_unpair *)xfer->xfer_buf; + req->nav_id = nav_id; + req->src_thread = src_thread; + req->dst_thread = dst_thread; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "RM_PSIL:Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_rm_udmap_tx_ch_cfg() - Configure a UDMAP TX channel + * @handle: Pointer to TI SCI handle. + * @params: Pointer to ti_sci_msg_rm_udmap_tx_ch_cfg TX channel config + * structure + * + * Return: 0 if all went well, else returns appropriate error value. + * + * See @ti_sci_msg_rm_udmap_tx_ch_cfg and @ti_sci_msg_rm_udmap_tx_ch_cfg_req for + * more info. + */ +static int ti_sci_cmd_rm_udmap_tx_ch_cfg(const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_tx_ch_cfg *params) +{ + struct ti_sci_msg_rm_udmap_tx_ch_cfg_req *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + struct device *dev; + int ret = 0; + + if (IS_ERR_OR_NULL(handle)) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TISCI_MSG_RM_UDMAP_TX_CH_CFG, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message TX_CH_CFG alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_rm_udmap_tx_ch_cfg_req *)xfer->xfer_buf; + req->valid_params = params->valid_params; + req->nav_id = params->nav_id; + req->index = params->index; + req->tx_pause_on_err = params->tx_pause_on_err; + req->tx_filt_einfo = params->tx_filt_einfo; + req->tx_filt_pswords = params->tx_filt_pswords; + req->tx_atype = params->tx_atype; + req->tx_chan_type = params->tx_chan_type; + req->tx_supr_tdpkt = params->tx_supr_tdpkt; + req->tx_fetch_size = params->tx_fetch_size; + req->tx_credit_count = params->tx_credit_count; + req->txcq_qnum = params->txcq_qnum; + req->tx_priority = params->tx_priority; + req->tx_qos = params->tx_qos; + req->tx_orderid = params->tx_orderid; + req->fdepth = params->fdepth; + req->tx_sched_priority = params->tx_sched_priority; + req->tx_burst_size = params->tx_burst_size; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send TX_CH_CFG fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + dev_dbg(info->dev, "TX_CH_CFG: chn %u ret:%u\n", params->index, ret); + return ret; +} + +/** + * ti_sci_cmd_rm_udmap_rx_ch_cfg() - Configure a UDMAP RX channel + * @handle: Pointer to TI SCI handle. + * @params: Pointer to ti_sci_msg_rm_udmap_rx_ch_cfg RX channel config + * structure + * + * Return: 0 if all went well, else returns appropriate error value. + * + * See @ti_sci_msg_rm_udmap_rx_ch_cfg and @ti_sci_msg_rm_udmap_rx_ch_cfg_req for + * more info. + */ +static int ti_sci_cmd_rm_udmap_rx_ch_cfg(const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_rx_ch_cfg *params) +{ + struct ti_sci_msg_rm_udmap_rx_ch_cfg_req *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + struct device *dev; + int ret = 0; + + if (IS_ERR_OR_NULL(handle)) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TISCI_MSG_RM_UDMAP_RX_CH_CFG, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message RX_CH_CFG alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_rm_udmap_rx_ch_cfg_req *)xfer->xfer_buf; + req->valid_params = params->valid_params; + req->nav_id = params->nav_id; + req->index = params->index; + req->rx_fetch_size = params->rx_fetch_size; + req->rxcq_qnum = params->rxcq_qnum; + req->rx_priority = params->rx_priority; + req->rx_qos = params->rx_qos; + req->rx_orderid = params->rx_orderid; + req->rx_sched_priority = params->rx_sched_priority; + req->flowid_start = params->flowid_start; + req->flowid_cnt = params->flowid_cnt; + req->rx_pause_on_err = params->rx_pause_on_err; + req->rx_atype = params->rx_atype; + req->rx_chan_type = params->rx_chan_type; + req->rx_ignore_short = params->rx_ignore_short; + req->rx_ignore_long = params->rx_ignore_long; + req->rx_burst_size = params->rx_burst_size; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send RX_CH_CFG fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + dev_dbg(info->dev, "RX_CH_CFG: chn %u ret:%d\n", params->index, ret); + return ret; +} + +/** + * ti_sci_cmd_rm_udmap_rx_flow_cfg() - Configure UDMAP RX FLOW + * @handle: Pointer to TI SCI handle. + * @params: Pointer to ti_sci_msg_rm_udmap_flow_cfg RX FLOW config + * structure + * + * Return: 0 if all went well, else returns appropriate error value. + * + * See @ti_sci_msg_rm_udmap_flow_cfg and @ti_sci_msg_rm_udmap_flow_cfg_req for + * more info. + */ +static int ti_sci_cmd_rm_udmap_rx_flow_cfg(const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_flow_cfg *params) +{ + struct ti_sci_msg_rm_udmap_flow_cfg_req *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + struct device *dev; + int ret = 0; + + if (IS_ERR_OR_NULL(handle)) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TISCI_MSG_RM_UDMAP_FLOW_CFG, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "RX_FL_CFG: Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_rm_udmap_flow_cfg_req *)xfer->xfer_buf; + req->valid_params = params->valid_params; + req->nav_id = params->nav_id; + req->flow_index = params->flow_index; + req->rx_einfo_present = params->rx_einfo_present; + req->rx_psinfo_present = params->rx_psinfo_present; + req->rx_error_handling = params->rx_error_handling; + req->rx_desc_type = params->rx_desc_type; + req->rx_sop_offset = params->rx_sop_offset; + req->rx_dest_qnum = params->rx_dest_qnum; + req->rx_src_tag_hi = params->rx_src_tag_hi; + req->rx_src_tag_lo = params->rx_src_tag_lo; + req->rx_dest_tag_hi = params->rx_dest_tag_hi; + req->rx_dest_tag_lo = params->rx_dest_tag_lo; + req->rx_src_tag_hi_sel = params->rx_src_tag_hi_sel; + req->rx_src_tag_lo_sel = params->rx_src_tag_lo_sel; + req->rx_dest_tag_hi_sel = params->rx_dest_tag_hi_sel; + req->rx_dest_tag_lo_sel = params->rx_dest_tag_lo_sel; + req->rx_fdq0_sz0_qnum = params->rx_fdq0_sz0_qnum; + req->rx_fdq1_qnum = params->rx_fdq1_qnum; + req->rx_fdq2_qnum = params->rx_fdq2_qnum; + req->rx_fdq3_qnum = params->rx_fdq3_qnum; + req->rx_ps_location = params->rx_ps_location; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "RX_FL_CFG: Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + dev_dbg(info->dev, "RX_FL_CFG: %u ret:%d\n", params->flow_index, ret); + return ret; +} + /* * ti_sci_setup_ops() - Setup the operations structures * @info: pointer to TISCI pointer @@ -2016,6 +2491,9 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) struct ti_sci_clk_ops *cops = &ops->clk_ops; struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops; struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_ops; + struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops; + struct ti_sci_rm_psil_ops *psilops = &ops->rm_psil_ops; + struct ti_sci_rm_udmap_ops *udmap_ops = &ops->rm_udmap_ops; core_ops->reboot_device = ti_sci_cmd_core_reboot; @@ -2055,6 +2533,16 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) iops->set_event_map = ti_sci_cmd_set_event_map; iops->free_irq = ti_sci_cmd_free_irq; iops->free_event_map = ti_sci_cmd_free_event_map; + + rops->config = ti_sci_cmd_ring_config; + rops->get_config = ti_sci_cmd_ring_get_config; + + psilops->pair = ti_sci_cmd_rm_psil_pair; + psilops->unpair = ti_sci_cmd_rm_psil_unpair; + + udmap_ops->tx_ch_cfg = ti_sci_cmd_rm_udmap_tx_ch_cfg; + udmap_ops->rx_ch_cfg = ti_sci_cmd_rm_udmap_rx_ch_cfg; + udmap_ops->rx_flow_cfg = ti_sci_cmd_rm_udmap_rx_flow_cfg; } /** diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 4983827151bf..2bb81ec7793c 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -42,6 +42,35 @@ #define TI_SCI_MSG_SET_IRQ 0x1000 #define TI_SCI_MSG_FREE_IRQ 0x1001 +/* NAVSS resource management */ +/* Ringacc requests */ +#define TI_SCI_MSG_RM_RING_ALLOCATE 0x1100 +#define TI_SCI_MSG_RM_RING_FREE 0x1101 +#define TI_SCI_MSG_RM_RING_RECONFIG 0x1102 +#define TI_SCI_MSG_RM_RING_RESET 0x1103 +#define TI_SCI_MSG_RM_RING_CFG 0x1110 +#define TI_SCI_MSG_RM_RING_GET_CFG 0x1111 + +/* PSI-L requests */ +#define TI_SCI_MSG_RM_PSIL_PAIR 0x1280 +#define TI_SCI_MSG_RM_PSIL_UNPAIR 0x1281 + +#define TI_SCI_MSG_RM_UDMAP_TX_ALLOC 0x1200 +#define TI_SCI_MSG_RM_UDMAP_TX_FREE 0x1201 +#define TI_SCI_MSG_RM_UDMAP_RX_ALLOC 0x1210 +#define TI_SCI_MSG_RM_UDMAP_RX_FREE 0x1211 +#define TI_SCI_MSG_RM_UDMAP_FLOW_CFG 0x1220 +#define TI_SCI_MSG_RM_UDMAP_OPT_FLOW_CFG 0x1221 + +#define TISCI_MSG_RM_UDMAP_TX_CH_CFG 0x1205 +#define TISCI_MSG_RM_UDMAP_TX_CH_GET_CFG 0x1206 +#define TISCI_MSG_RM_UDMAP_RX_CH_CFG 0x1215 +#define TISCI_MSG_RM_UDMAP_RX_CH_GET_CFG 0x1216 +#define TISCI_MSG_RM_UDMAP_FLOW_CFG 0x1230 +#define TISCI_MSG_RM_UDMAP_FLOW_SIZE_THRESH_CFG 0x1231 +#define TISCI_MSG_RM_UDMAP_FLOW_GET_CFG 0x1232 +#define TISCI_MSG_RM_UDMAP_FLOW_SIZE_THRESH_GET_CFG 0x1233 + /** * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses * @type: Type of messages: One of TI_SCI_MSG* values @@ -563,4 +592,650 @@ struct ti_sci_msg_req_manage_irq { u8 secondary_host; } __packed; +/** + * struct ti_sci_msg_rm_ring_cfg_req - Configure a Navigator Subsystem ring + * + * Configures the non-real-time registers of a Navigator Subsystem ring. + * @hdr: Generic Header + * @valid_params: Bitfield defining validity of ring configuration parameters. + * The ring configuration fields are not valid, and will not be used for + * ring configuration, if their corresponding valid bit is zero. + * Valid bit usage: + * 0 - Valid bit for @tisci_msg_rm_ring_cfg_req addr_lo + * 1 - Valid bit for @tisci_msg_rm_ring_cfg_req addr_hi + * 2 - Valid bit for @tisci_msg_rm_ring_cfg_req count + * 3 - Valid bit for @tisci_msg_rm_ring_cfg_req mode + * 4 - Valid bit for @tisci_msg_rm_ring_cfg_req size + * 5 - Valid bit for @tisci_msg_rm_ring_cfg_req order_id + * @nav_id: Device ID of Navigator Subsystem from which the ring is allocated + * @index: ring index to be configured. + * @addr_lo: 32 LSBs of ring base address to be programmed into the ring's + * RING_BA_LO register + * @addr_hi: 16 MSBs of ring base address to be programmed into the ring's + * RING_BA_HI register. + * @count: Number of ring elements. Must be even if mode is CREDENTIALS or QM + * modes. + * @mode: Specifies the mode the ring is to be configured. + * @size: Specifies encoded ring element size. To calculate the encoded size use + * the formula (log2(size_bytes) - 2), where size_bytes cannot be + * greater than 256. + * @order_id: Specifies the ring's bus order ID. + */ +struct ti_sci_msg_rm_ring_cfg_req { + struct ti_sci_msg_hdr hdr; + u32 valid_params; + u16 nav_id; + u16 index; + u32 addr_lo; + u32 addr_hi; + u32 count; + u8 mode; + u8 size; + u8 order_id; +} __packed; + +/** + * struct ti_sci_msg_rm_ring_get_cfg_req - Get RA ring's configuration + * + * Gets the configuration of the non-real-time register fields of a ring. The + * host, or a supervisor of the host, who owns the ring must be the requesting + * host. The values of the non-real-time registers are returned in + * @ti_sci_msg_rm_ring_get_cfg_resp. + * + * @hdr: Generic Header + * @nav_id: Device ID of Navigator Subsystem from which the ring is allocated + * @index: ring index. + */ +struct ti_sci_msg_rm_ring_get_cfg_req { + struct ti_sci_msg_hdr hdr; + u16 nav_id; + u16 index; +} __packed; + +/** + * struct ti_sci_msg_rm_ring_get_cfg_resp - Ring get configuration response + * + * Response received by host processor after RM has handled + * @ti_sci_msg_rm_ring_get_cfg_req. The response contains the ring's + * non-real-time register values. + * + * @hdr: Generic Header + * @addr_lo: Ring 32 LSBs of base address + * @addr_hi: Ring 16 MSBs of base address. + * @count: Ring number of elements. + * @mode: Ring mode. + * @size: encoded Ring element size + * @order_id: ing order ID. + */ +struct ti_sci_msg_rm_ring_get_cfg_resp { + struct ti_sci_msg_hdr hdr; + u32 addr_lo; + u32 addr_hi; + u32 count; + u8 mode; + u8 size; + u8 order_id; +} __packed; + +/** + * struct ti_sci_msg_psil_pair - Pairs a PSI-L source thread to a destination + * thread + * @hdr: Generic Header + * @nav_id: SoC Navigator Subsystem device ID whose PSI-L config proxy is + * used to pair the source and destination threads. + * @src_thread: PSI-L source thread ID within the PSI-L System thread map. + * + * UDMAP transmit channels mapped to source threads will have their + * TCHAN_THRD_ID register programmed with the destination thread if the pairing + * is successful. + + * @dst_thread: PSI-L destination thread ID within the PSI-L System thread map. + * PSI-L destination threads start at index 0x8000. The request is NACK'd if + * the destination thread is not greater than or equal to 0x8000. + * + * UDMAP receive channels mapped to destination threads will have their + * RCHAN_THRD_ID register programmed with the source thread if the pairing + * is successful. + * + * Request type is TI_SCI_MSG_RM_PSIL_PAIR, response is a generic ACK or NACK + * message. + */ +struct ti_sci_msg_psil_pair { + struct ti_sci_msg_hdr hdr; + u32 nav_id; + u32 src_thread; + u32 dst_thread; +} __packed; + +/** + * struct ti_sci_msg_psil_unpair - Unpairs a PSI-L source thread from a + * destination thread + * @hdr: Generic Header + * @nav_id: SoC Navigator Subsystem device ID whose PSI-L config proxy is + * used to unpair the source and destination threads. + * @src_thread: PSI-L source thread ID within the PSI-L System thread map. + * + * UDMAP transmit channels mapped to source threads will have their + * TCHAN_THRD_ID register cleared if the unpairing is successful. + * + * @dst_thread: PSI-L destination thread ID within the PSI-L System thread map. + * PSI-L destination threads start at index 0x8000. The request is NACK'd if + * the destination thread is not greater than or equal to 0x8000. + * + * UDMAP receive channels mapped to destination threads will have their + * RCHAN_THRD_ID register cleared if the unpairing is successful. + * + * Request type is TI_SCI_MSG_RM_PSIL_UNPAIR, response is a generic ACK or NACK + * message. + */ +struct ti_sci_msg_psil_unpair { + struct ti_sci_msg_hdr hdr; + u32 nav_id; + u32 src_thread; + u32 dst_thread; +} __packed; + +/** + * struct ti_sci_msg_udmap_rx_flow_cfg - UDMAP receive flow configuration + * message + * @hdr: Generic Header + * @nav_id: SoC Navigator Subsystem device ID from which the receive flow is + * allocated + * @flow_index: UDMAP receive flow index for non-optional configuration. + * @rx_ch_index: Specifies the index of the receive channel using the flow_index + * @rx_einfo_present: UDMAP receive flow extended packet info present. + * @rx_psinfo_present: UDMAP receive flow PS words present. + * @rx_error_handling: UDMAP receive flow error handling configuration. Valid + * values are TI_SCI_RM_UDMAP_RX_FLOW_ERR_DROP/RETRY. + * @rx_desc_type: UDMAP receive flow descriptor type. It can be one of + * TI_SCI_RM_UDMAP_RX_FLOW_DESC_HOST/MONO. + * @rx_sop_offset: UDMAP receive flow start of packet offset. + * @rx_dest_qnum: UDMAP receive flow destination queue number. + * @rx_ps_location: UDMAP receive flow PS words location. + * 0 - end of packet descriptor + * 1 - Beginning of the data buffer + * @rx_src_tag_hi: UDMAP receive flow source tag high byte constant + * @rx_src_tag_lo: UDMAP receive flow source tag low byte constant + * @rx_dest_tag_hi: UDMAP receive flow destination tag high byte constant + * @rx_dest_tag_lo: UDMAP receive flow destination tag low byte constant + * @rx_src_tag_hi_sel: UDMAP receive flow source tag high byte selector + * @rx_src_tag_lo_sel: UDMAP receive flow source tag low byte selector + * @rx_dest_tag_hi_sel: UDMAP receive flow destination tag high byte selector + * @rx_dest_tag_lo_sel: UDMAP receive flow destination tag low byte selector + * @rx_size_thresh_en: UDMAP receive flow packet size based free buffer queue + * enable. If enabled, the ti_sci_rm_udmap_rx_flow_opt_cfg also need to be + * configured and sent. + * @rx_fdq0_sz0_qnum: UDMAP receive flow free descriptor queue 0. + * @rx_fdq1_qnum: UDMAP receive flow free descriptor queue 1. + * @rx_fdq2_qnum: UDMAP receive flow free descriptor queue 2. + * @rx_fdq3_qnum: UDMAP receive flow free descriptor queue 3. + * + * For detailed information on the settings, see the UDMAP section of the TRM. + */ +struct ti_sci_msg_udmap_rx_flow_cfg { + struct ti_sci_msg_hdr hdr; + u32 nav_id; + u32 flow_index; + u32 rx_ch_index; + u8 rx_einfo_present; + u8 rx_psinfo_present; + u8 rx_error_handling; + u8 rx_desc_type; + u16 rx_sop_offset; + u16 rx_dest_qnum; + u8 rx_ps_location; + u8 rx_src_tag_hi; + u8 rx_src_tag_lo; + u8 rx_dest_tag_hi; + u8 rx_dest_tag_lo; + u8 rx_src_tag_hi_sel; + u8 rx_src_tag_lo_sel; + u8 rx_dest_tag_hi_sel; + u8 rx_dest_tag_lo_sel; + u8 rx_size_thresh_en; + u16 rx_fdq0_sz0_qnum; + u16 rx_fdq1_qnum; + u16 rx_fdq2_qnum; + u16 rx_fdq3_qnum; +} __packed; + +/** + * struct rm_ti_sci_msg_udmap_rx_flow_opt_cfg - parameters for UDMAP receive + * flow optional configuration + * @hdr: Generic Header + * @nav_id: SoC Navigator Subsystem device ID from which the receive flow is + * allocated + * @flow_index: UDMAP receive flow index for optional configuration. + * @rx_ch_index: Specifies the index of the receive channel using the flow_index + * @rx_size_thresh0: UDMAP receive flow packet size threshold 0. + * @rx_size_thresh1: UDMAP receive flow packet size threshold 1. + * @rx_size_thresh2: UDMAP receive flow packet size threshold 2. + * @rx_fdq0_sz1_qnum: UDMAP receive flow free descriptor queue for size + * threshold 1. + * @rx_fdq0_sz2_qnum: UDMAP receive flow free descriptor queue for size + * threshold 2. + * @rx_fdq0_sz3_qnum: UDMAP receive flow free descriptor queue for size + * threshold 3. + * + * For detailed information on the settings, see the UDMAP section of the TRM. + */ +struct rm_ti_sci_msg_udmap_rx_flow_opt_cfg { + struct ti_sci_msg_hdr hdr; + u32 nav_id; + u32 flow_index; + u32 rx_ch_index; + u16 rx_size_thresh0; + u16 rx_size_thresh1; + u16 rx_size_thresh2; + u16 rx_fdq0_sz1_qnum; + u16 rx_fdq0_sz2_qnum; + u16 rx_fdq0_sz3_qnum; +} __packed; + +/** + * Configures a Navigator Subsystem UDMAP transmit channel + * + * Configures the non-real-time registers of a Navigator Subsystem UDMAP + * transmit channel. The channel index must be assigned to the host defined + * in the TISCI header via the RM board configuration resource assignment + * range list. + * + * @hdr: Generic Header + * + * @valid_params: Bitfield defining validity of tx channel configuration + * parameters. The tx channel configuration fields are not valid, and will not + * be used for ch configuration, if their corresponding valid bit is zero. + * Valid bit usage: + * 0 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_pause_on_err + * 1 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_atype + * 2 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_chan_type + * 3 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_fetch_size + * 4 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::txcq_qnum + * 5 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_priority + * 6 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_qos + * 7 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_orderid + * 8 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_sched_priority + * 9 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_filt_einfo + * 10 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_filt_pswords + * 11 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_supr_tdpkt + * 12 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_credit_count + * 13 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::fdepth + * 14 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_burst_size + * + * @nav_id: SoC device ID of Navigator Subsystem where tx channel is located + * + * @index: UDMAP transmit channel index. + * + * @tx_pause_on_err: UDMAP transmit channel pause on error configuration to + * be programmed into the tx_pause_on_err field of the channel's TCHAN_TCFG + * register. + * + * @tx_filt_einfo: UDMAP transmit channel extended packet information passing + * configuration to be programmed into the tx_filt_einfo field of the + * channel's TCHAN_TCFG register. + * + * @tx_filt_pswords: UDMAP transmit channel protocol specific word passing + * configuration to be programmed into the tx_filt_pswords field of the + * channel's TCHAN_TCFG register. + * + * @tx_atype: UDMAP transmit channel non Ring Accelerator access pointer + * interpretation configuration to be programmed into the tx_atype field of + * the channel's TCHAN_TCFG register. + * + * @tx_chan_type: UDMAP transmit channel functional channel type and work + * passing mechanism configuration to be programmed into the tx_chan_type + * field of the channel's TCHAN_TCFG register. + * + * @tx_supr_tdpkt: UDMAP transmit channel teardown packet generation suppression + * configuration to be programmed into the tx_supr_tdpkt field of the channel's + * TCHAN_TCFG register. + * + * @tx_fetch_size: UDMAP transmit channel number of 32-bit descriptor words to + * fetch configuration to be programmed into the tx_fetch_size field of the + * channel's TCHAN_TCFG register. The user must make sure to set the maximum + * word count that can pass through the channel for any allowed descriptor type. + * + * @tx_credit_count: UDMAP transmit channel transfer request credit count + * configuration to be programmed into the count field of the TCHAN_TCREDIT + * register. Specifies how many credits for complete TRs are available. + * + * @txcq_qnum: UDMAP transmit channel completion queue configuration to be + * programmed into the txcq_qnum field of the TCHAN_TCQ register. The specified + * completion queue must be assigned to the host, or a subordinate of the host, + * requesting configuration of the transmit channel. + * + * @tx_priority: UDMAP transmit channel transmit priority value to be programmed + * into the priority field of the channel's TCHAN_TPRI_CTRL register. + * + * @tx_qos: UDMAP transmit channel transmit qos value to be programmed into the + * qos field of the channel's TCHAN_TPRI_CTRL register. + * + * @tx_orderid: UDMAP transmit channel bus order id value to be programmed into + * the orderid field of the channel's TCHAN_TPRI_CTRL register. + * + * @fdepth: UDMAP transmit channel FIFO depth configuration to be programmed + * into the fdepth field of the TCHAN_TFIFO_DEPTH register. Sets the number of + * Tx FIFO bytes which are allowed to be stored for the channel. Check the UDMAP + * section of the TRM for restrictions regarding this parameter. + * + * @tx_sched_priority: UDMAP transmit channel tx scheduling priority + * configuration to be programmed into the priority field of the channel's + * TCHAN_TST_SCHED register. + * + * @tx_burst_size: UDMAP transmit channel burst size configuration to be + * programmed into the tx_burst_size field of the TCHAN_TCFG register. + */ +struct ti_sci_msg_rm_udmap_tx_ch_cfg_req { + struct ti_sci_msg_hdr hdr; + u32 valid_params; + u16 nav_id; + u16 index; + u8 tx_pause_on_err; + u8 tx_filt_einfo; + u8 tx_filt_pswords; + u8 tx_atype; + u8 tx_chan_type; + u8 tx_supr_tdpkt; + u16 tx_fetch_size; + u8 tx_credit_count; + u16 txcq_qnum; + u8 tx_priority; + u8 tx_qos; + u8 tx_orderid; + u16 fdepth; + u8 tx_sched_priority; + u8 tx_burst_size; +} __packed; + +/** + * Configures a Navigator Subsystem UDMAP receive channel + * + * Configures the non-real-time registers of a Navigator Subsystem UDMAP + * receive channel. The channel index must be assigned to the host defined + * in the TISCI header via the RM board configuration resource assignment + * range list. + * + * @hdr: Generic Header + * + * @valid_params: Bitfield defining validity of rx channel configuration + * parameters. + * The rx channel configuration fields are not valid, and will not be used for + * ch configuration, if their corresponding valid bit is zero. + * Valid bit usage: + * 0 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_pause_on_err + * 1 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_atype + * 2 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_chan_type + * 3 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_fetch_size + * 4 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rxcq_qnum + * 5 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_priority + * 6 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_qos + * 7 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_orderid + * 8 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_sched_priority + * 9 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::flowid_start + * 10 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::flowid_cnt + * 11 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_ignore_short + * 12 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_ignore_long + * 14 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_burst_size + * + * @nav_id: SoC device ID of Navigator Subsystem where rx channel is located + * + * @index: UDMAP receive channel index. + * + * @rx_fetch_size: UDMAP receive channel number of 32-bit descriptor words to + * fetch configuration to be programmed into the rx_fetch_size field of the + * channel's RCHAN_RCFG register. + * + * @rxcq_qnum: UDMAP receive channel completion queue configuration to be + * programmed into the rxcq_qnum field of the RCHAN_RCQ register. + * The specified completion queue must be assigned to the host, or a subordinate + * of the host, requesting configuration of the receive channel. + * + * @rx_priority: UDMAP receive channel receive priority value to be programmed + * into the priority field of the channel's RCHAN_RPRI_CTRL register. + * + * @rx_qos: UDMAP receive channel receive qos value to be programmed into the + * qos field of the channel's RCHAN_RPRI_CTRL register. + * + * @rx_orderid: UDMAP receive channel bus order id value to be programmed into + * the orderid field of the channel's RCHAN_RPRI_CTRL register. + * + * @rx_sched_priority: UDMAP receive channel rx scheduling priority + * configuration to be programmed into the priority field of the channel's + * RCHAN_RST_SCHED register. + * + * @flowid_start: UDMAP receive channel additional flows starting index + * configuration to program into the flow_start field of the RCHAN_RFLOW_RNG + * register. Specifies the starting index for flow IDs the receive channel is to + * make use of beyond the default flow. flowid_start and @ref flowid_cnt must be + * set as valid and configured together. The starting flow ID set by + * @ref flowid_cnt must be a flow index within the Navigator Subsystem's subset + * of flows beyond the default flows statically mapped to receive channels. + * The additional flows must be assigned to the host, or a subordinate of the + * host, requesting configuration of the receive channel. + * + * @flowid_cnt: UDMAP receive channel additional flows count configuration to + * program into the flowid_cnt field of the RCHAN_RFLOW_RNG register. + * This field specifies how many flow IDs are in the additional contiguous range + * of legal flow IDs for the channel. @ref flowid_start and flowid_cnt must be + * set as valid and configured together. Disabling the valid_params field bit + * for flowid_cnt indicates no flow IDs other than the default are to be + * allocated and used by the receive channel. @ref flowid_start plus flowid_cnt + * cannot be greater than the number of receive flows in the receive channel's + * Navigator Subsystem. The additional flows must be assigned to the host, or a + * subordinate of the host, requesting configuration of the receive channel. + * + * @rx_pause_on_err: UDMAP receive channel pause on error configuration to be + * programmed into the rx_pause_on_err field of the channel's RCHAN_RCFG + * register. + * + * @rx_atype: UDMAP receive channel non Ring Accelerator access pointer + * interpretation configuration to be programmed into the rx_atype field of the + * channel's RCHAN_RCFG register. + * + * @rx_chan_type: UDMAP receive channel functional channel type and work passing + * mechanism configuration to be programmed into the rx_chan_type field of the + * channel's RCHAN_RCFG register. + * + * @rx_ignore_short: UDMAP receive channel short packet treatment configuration + * to be programmed into the rx_ignore_short field of the RCHAN_RCFG register. + * + * @rx_ignore_long: UDMAP receive channel long packet treatment configuration to + * be programmed into the rx_ignore_long field of the RCHAN_RCFG register. + * + * @rx_burst_size: UDMAP receive channel burst size configuration to be + * programmed into the rx_burst_size field of the RCHAN_RCFG register. + */ +struct ti_sci_msg_rm_udmap_rx_ch_cfg_req { + struct ti_sci_msg_hdr hdr; + u32 valid_params; + u16 nav_id; + u16 index; + u16 rx_fetch_size; + u16 rxcq_qnum; + u8 rx_priority; + u8 rx_qos; + u8 rx_orderid; + u8 rx_sched_priority; + u16 flowid_start; + u16 flowid_cnt; + u8 rx_pause_on_err; + u8 rx_atype; + u8 rx_chan_type; + u8 rx_ignore_short; + u8 rx_ignore_long; + u8 rx_burst_size; +} __packed; + +/** + * Configures a Navigator Subsystem UDMAP receive flow + * + * Configures a Navigator Subsystem UDMAP receive flow's registers. + * Configuration does not include the flow registers which handle size-based + * free descriptor queue routing. + * + * The flow index must be assigned to the host defined in the TISCI header via + * the RM board configuration resource assignment range list. + * + * @hdr: Standard TISCI header + * + * @valid_params + * Bitfield defining validity of rx flow configuration parameters. The + * rx flow configuration fields are not valid, and will not be used for flow + * configuration, if their corresponding valid bit is zero. Valid bit usage: + * 0 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_einfo_present + * 1 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_psinfo_present + * 2 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_error_handling + * 3 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_desc_type + * 4 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_sop_offset + * 5 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_qnum + * 6 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_hi + * 7 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_lo + * 8 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_hi + * 9 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_lo + * 10 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_hi_sel + * 11 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_lo_sel + * 12 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_hi_sel + * 13 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_lo_sel + * 14 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_fdq0_sz0_qnum + * 15 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_fdq1_sz0_qnum + * 16 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_fdq2_sz0_qnum + * 17 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_fdq3_sz0_qnum + * 18 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_ps_location + * + * @nav_id: SoC device ID of Navigator Subsystem from which the receive flow is + * allocated + * + * @flow_index: UDMAP receive flow index for non-optional configuration. + * + * @rx_einfo_present: + * UDMAP receive flow extended packet info present configuration to be + * programmed into the rx_einfo_present field of the flow's RFLOW_RFA register. + * + * @rx_psinfo_present: + * UDMAP receive flow PS words present configuration to be programmed into the + * rx_psinfo_present field of the flow's RFLOW_RFA register. + * + * @rx_error_handling: + * UDMAP receive flow error handling configuration to be programmed into the + * rx_error_handling field of the flow's RFLOW_RFA register. + * + * @rx_desc_type: + * UDMAP receive flow descriptor type configuration to be programmed into the + * rx_desc_type field field of the flow's RFLOW_RFA register. + * + * @rx_sop_offset: + * UDMAP receive flow start of packet offset configuration to be programmed + * into the rx_sop_offset field of the RFLOW_RFA register. See the UDMAP + * section of the TRM for more information on this setting. Valid values for + * this field are 0-255 bytes. + * + * @rx_dest_qnum: + * UDMAP receive flow destination queue configuration to be programmed into the + * rx_dest_qnum field of the flow's RFLOW_RFA register. The specified + * destination queue must be valid within the Navigator Subsystem and must be + * owned by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @rx_src_tag_hi: + * UDMAP receive flow source tag high byte constant configuration to be + * programmed into the rx_src_tag_hi field of the flow's RFLOW_RFB register. + * See the UDMAP section of the TRM for more information on this setting. + * + * @rx_src_tag_lo: + * UDMAP receive flow source tag low byte constant configuration to be + * programmed into the rx_src_tag_lo field of the flow's RFLOW_RFB register. + * See the UDMAP section of the TRM for more information on this setting. + * + * @rx_dest_tag_hi: + * UDMAP receive flow destination tag high byte constant configuration to be + * programmed into the rx_dest_tag_hi field of the flow's RFLOW_RFB register. + * See the UDMAP section of the TRM for more information on this setting. + * + * @rx_dest_tag_lo: + * UDMAP receive flow destination tag low byte constant configuration to be + * programmed into the rx_dest_tag_lo field of the flow's RFLOW_RFB register. + * See the UDMAP section of the TRM for more information on this setting. + * + * @rx_src_tag_hi_sel: + * UDMAP receive flow source tag high byte selector configuration to be + * programmed into the rx_src_tag_hi_sel field of the RFLOW_RFC register. See + * the UDMAP section of the TRM for more information on this setting. + * + * @rx_src_tag_lo_sel: + * UDMAP receive flow source tag low byte selector configuration to be + * programmed into the rx_src_tag_lo_sel field of the RFLOW_RFC register. See + * the UDMAP section of the TRM for more information on this setting. + * + * @rx_dest_tag_hi_sel: + * UDMAP receive flow destination tag high byte selector configuration to be + * programmed into the rx_dest_tag_hi_sel field of the RFLOW_RFC register. See + * the UDMAP section of the TRM for more information on this setting. + * + * @rx_dest_tag_lo_sel: + * UDMAP receive flow destination tag low byte selector configuration to be + * programmed into the rx_dest_tag_lo_sel field of the RFLOW_RFC register. See + * the UDMAP section of the TRM for more information on this setting. + * + * @rx_fdq0_sz0_qnum: + * UDMAP receive flow free descriptor queue 0 configuration to be programmed + * into the rx_fdq0_sz0_qnum field of the flow's RFLOW_RFD register. See the + * UDMAP section of the TRM for more information on this setting. The specified + * free queue must be valid within the Navigator Subsystem and must be owned + * by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @rx_fdq1_qnum: + * UDMAP receive flow free descriptor queue 1 configuration to be programmed + * into the rx_fdq1_qnum field of the flow's RFLOW_RFD register. See the + * UDMAP section of the TRM for more information on this setting. The specified + * free queue must be valid within the Navigator Subsystem and must be owned + * by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @rx_fdq2_qnum: + * UDMAP receive flow free descriptor queue 2 configuration to be programmed + * into the rx_fdq2_qnum field of the flow's RFLOW_RFE register. See the + * UDMAP section of the TRM for more information on this setting. The specified + * free queue must be valid within the Navigator Subsystem and must be owned + * by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @rx_fdq3_qnum: + * UDMAP receive flow free descriptor queue 3 configuration to be programmed + * into the rx_fdq3_qnum field of the flow's RFLOW_RFE register. See the + * UDMAP section of the TRM for more information on this setting. The specified + * free queue must be valid within the Navigator Subsystem and must be owned + * by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @rx_ps_location: + * UDMAP receive flow PS words location configuration to be programmed into the + * rx_ps_location field of the flow's RFLOW_RFA register. + */ +struct ti_sci_msg_rm_udmap_flow_cfg_req { + struct ti_sci_msg_hdr hdr; + u32 valid_params; + u16 nav_id; + u16 flow_index; + u8 rx_einfo_present; + u8 rx_psinfo_present; + u8 rx_error_handling; + u8 rx_desc_type; + u16 rx_sop_offset; + u16 rx_dest_qnum; + u8 rx_src_tag_hi; + u8 rx_src_tag_lo; + u8 rx_dest_tag_hi; + u8 rx_dest_tag_lo; + u8 rx_src_tag_hi_sel; + u8 rx_src_tag_lo_sel; + u8 rx_dest_tag_hi_sel; + u8 rx_dest_tag_lo_sel; + u16 rx_fdq0_sz0_qnum; + u16 rx_fdq1_qnum; + u16 rx_fdq2_qnum; + u16 rx_fdq3_qnum; + u8 rx_ps_location; +} __packed; + #endif /* __TI_SCI_H */ diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index 568722a041bf..4fd9bff5806b 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -241,6 +241,218 @@ struct ti_sci_rm_irq_ops { u16 global_event, u8 vint_status_bit); }; +/* RA config.addr_lo parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_ADDR_LO_VALID BIT(0) +/* RA config.addr_hi parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_ADDR_HI_VALID BIT(1) + /* RA config.count parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_COUNT_VALID BIT(2) +/* RA config.mode parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_MODE_VALID BIT(3) +/* RA config.size parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_SIZE_VALID BIT(4) +/* RA config.order_id parameter is valid for RM ring configure TISCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_ORDER_ID_VALID BIT(5) + +#define TI_SCI_MSG_VALUE_RM_ALL_NO_ORDER \ + (TI_SCI_MSG_VALUE_RM_RING_ADDR_LO_VALID | \ + TI_SCI_MSG_VALUE_RM_RING_ADDR_HI_VALID | \ + TI_SCI_MSG_VALUE_RM_RING_COUNT_VALID | \ + TI_SCI_MSG_VALUE_RM_RING_MODE_VALID | \ + TI_SCI_MSG_VALUE_RM_RING_SIZE_VALID) + +/** + * struct ti_sci_rm_ringacc_ops - Ring Accelerator Management operations + * @config: configure the SoC Navigator Subsystem Ring Accelerator ring + * @get_config: get the SoC Navigator Subsystem Ring Accelerator ring + * configuration + */ +struct ti_sci_rm_ringacc_ops { + int (*config)(const struct ti_sci_handle *handle, + u32 valid_params, u16 nav_id, u16 index, + u32 addr_lo, u32 addr_hi, u32 count, u8 mode, + u8 size, u8 order_id + ); + int (*get_config)(const struct ti_sci_handle *handle, + u32 nav_id, u32 index, u8 *mode, + u32 *addr_lo, u32 *addr_hi, u32 *count, + u8 *size, u8 *order_id); +}; + +/** + * struct ti_sci_rm_psil_ops - PSI-L thread operations + * @pair: pair PSI-L source thread to a destination thread. + * If the src_thread is mapped to UDMA tchan, the corresponding channel's + * TCHAN_THRD_ID register is updated. + * If the dst_thread is mapped to UDMA rchan, the corresponding channel's + * RCHAN_THRD_ID register is updated. + * @unpair: unpair PSI-L source thread from a destination thread. + * If the src_thread is mapped to UDMA tchan, the corresponding channel's + * TCHAN_THRD_ID register is cleared. + * If the dst_thread is mapped to UDMA rchan, the corresponding channel's + * RCHAN_THRD_ID register is cleared. + */ +struct ti_sci_rm_psil_ops { + int (*pair)(const struct ti_sci_handle *handle, u32 nav_id, + u32 src_thread, u32 dst_thread); + int (*unpair)(const struct ti_sci_handle *handle, u32 nav_id, + u32 src_thread, u32 dst_thread); +}; + +/* UDMAP channel types */ +#define TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR 2 +#define TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR_SB 3 /* RX only */ +#define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_PBRR 10 +#define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_PBVR 11 +#define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR 12 +#define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBVR 13 + +#define TI_SCI_RM_UDMAP_RX_FLOW_DESC_HOST 0 +#define TI_SCI_RM_UDMAP_RX_FLOW_DESC_MONO 2 + +#define TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_64_BYTES 1 +#define TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_128_BYTES 2 +#define TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_256_BYTES 3 + +/* UDMAP TX/RX channel valid_params common declarations */ +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_PAUSE_ON_ERR_VALID BIT(0) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_ATYPE_VALID BIT(1) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_CHAN_TYPE_VALID BIT(2) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_FETCH_SIZE_VALID BIT(3) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_CQ_QNUM_VALID BIT(4) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_PRIORITY_VALID BIT(5) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_QOS_VALID BIT(6) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_ORDER_ID_VALID BIT(7) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_SCHED_PRIORITY_VALID BIT(8) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_BURST_SIZE_VALID BIT(14) + +/** + * Configures a Navigator Subsystem UDMAP transmit channel + * + * Configures a Navigator Subsystem UDMAP transmit channel registers. + * See @ti_sci_msg_rm_udmap_tx_ch_cfg_req + */ +struct ti_sci_msg_rm_udmap_tx_ch_cfg { + u32 valid_params; +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_FILT_EINFO_VALID BIT(9) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_FILT_PSWORDS_VALID BIT(10) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_SUPR_TDPKT_VALID BIT(11) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_CREDIT_COUNT_VALID BIT(12) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_FDEPTH_VALID BIT(13) + u16 nav_id; + u16 index; + u8 tx_pause_on_err; + u8 tx_filt_einfo; + u8 tx_filt_pswords; + u8 tx_atype; + u8 tx_chan_type; + u8 tx_supr_tdpkt; + u16 tx_fetch_size; + u8 tx_credit_count; + u16 txcq_qnum; + u8 tx_priority; + u8 tx_qos; + u8 tx_orderid; + u16 fdepth; + u8 tx_sched_priority; + u8 tx_burst_size; +}; + +/** + * Configures a Navigator Subsystem UDMAP receive channel + * + * Configures a Navigator Subsystem UDMAP receive channel registers. + * See @ti_sci_msg_rm_udmap_rx_ch_cfg_req + */ +struct ti_sci_msg_rm_udmap_rx_ch_cfg { + u32 valid_params; +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_START_VALID BIT(9) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_CNT_VALID BIT(10) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_IGNORE_SHORT_VALID BIT(11) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_IGNORE_LONG_VALID BIT(12) + u16 nav_id; + u16 index; + u16 rx_fetch_size; + u16 rxcq_qnum; + u8 rx_priority; + u8 rx_qos; + u8 rx_orderid; + u8 rx_sched_priority; + u16 flowid_start; + u16 flowid_cnt; + u8 rx_pause_on_err; + u8 rx_atype; + u8 rx_chan_type; + u8 rx_ignore_short; + u8 rx_ignore_long; + u8 rx_burst_size; +}; + +/** + * Configures a Navigator Subsystem UDMAP receive flow + * + * Configures a Navigator Subsystem UDMAP receive flow's registers. + * See @tis_ci_msg_rm_udmap_flow_cfg_req + */ +struct ti_sci_msg_rm_udmap_flow_cfg { + u32 valid_params; +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_EINFO_PRESENT_VALID BIT(0) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_PSINFO_PRESENT_VALID BIT(1) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_ERROR_HANDLING_VALID BIT(2) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DESC_TYPE_VALID BIT(3) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SOP_OFFSET_VALID BIT(4) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_QNUM_VALID BIT(5) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_HI_VALID BIT(6) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_LO_VALID BIT(7) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_HI_VALID BIT(8) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_LO_VALID BIT(9) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_HI_SEL_VALID BIT(10) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_LO_SEL_VALID BIT(11) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_HI_SEL_VALID BIT(12) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_LO_SEL_VALID BIT(13) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ0_SZ0_QNUM_VALID BIT(14) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ1_QNUM_VALID BIT(15) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ2_QNUM_VALID BIT(16) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ3_QNUM_VALID BIT(17) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_PS_LOCATION_VALID BIT(18) + u16 nav_id; + u16 flow_index; + u8 rx_einfo_present; + u8 rx_psinfo_present; + u8 rx_error_handling; + u8 rx_desc_type; + u16 rx_sop_offset; + u16 rx_dest_qnum; + u8 rx_src_tag_hi; + u8 rx_src_tag_lo; + u8 rx_dest_tag_hi; + u8 rx_dest_tag_lo; + u8 rx_src_tag_hi_sel; + u8 rx_src_tag_lo_sel; + u8 rx_dest_tag_hi_sel; + u8 rx_dest_tag_lo_sel; + u16 rx_fdq0_sz0_qnum; + u16 rx_fdq1_qnum; + u16 rx_fdq2_qnum; + u16 rx_fdq3_qnum; + u8 rx_ps_location; +}; + +/** + * struct ti_sci_rm_udmap_ops - UDMA Management operations + * @tx_ch_cfg: configure SoC Navigator Subsystem UDMA transmit channel. + * @rx_ch_cfg: configure SoC Navigator Subsystem UDMA receive channel. + * @rx_flow_cfg1: configure SoC Navigator Subsystem UDMA receive flow. + */ +struct ti_sci_rm_udmap_ops { + int (*tx_ch_cfg)(const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_tx_ch_cfg *params); + int (*rx_ch_cfg)(const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_rx_ch_cfg *params); + int (*rx_flow_cfg)(const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_flow_cfg *params); +}; + /** * struct ti_sci_ops - Function support for TI SCI * @dev_ops: Device specific operations @@ -254,6 +466,9 @@ struct ti_sci_ops { struct ti_sci_clk_ops clk_ops; struct ti_sci_rm_core_ops rm_core_ops; struct ti_sci_rm_irq_ops rm_irq_ops; + struct ti_sci_rm_ringacc_ops rm_ring_ops; + struct ti_sci_rm_psil_ops rm_psil_ops; + struct ti_sci_rm_udmap_ops rm_udmap_ops; }; /** -- cgit v1.2.3 From 1e407f337f4015c8ffc56e7cfd70e06b2e9fc9da Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 5 Jun 2019 17:33:34 -0500 Subject: firmware: ti_sci: Add support for processor control Texas Instrument's System Control Interface (TI-SCI) Message Protocol is used in Texas Instrument's System on Chip (SoC) such as those in K3 family AM654 SoC to communicate between various compute processors with a central system controller entity. The system controller provides various services including the control of other compute processors within the SoC. Extend the TI-SCI protocol support to add various TI-SCI commands to invoke services associated with power and reset control, and boot vector management of the various compute processors from the Linux kernel. Signed-off-by: Suman Anna Signed-off-by: Tero Kristo Signed-off-by: Santosh Shilimkar --- drivers/firmware/ti_sci.c | 350 +++++++++++++++++++++++++++++++++ drivers/firmware/ti_sci.h | 135 +++++++++++++ include/linux/soc/ti/ti_sci_protocol.h | 31 +++ 3 files changed, 516 insertions(+) (limited to 'include') diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 02fa196428d8..b47e33e7411f 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -2479,6 +2479,348 @@ fail: return ret; } +/** + * ti_sci_cmd_proc_request() - Command to request a physical processor control + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_proc_request(const struct ti_sci_handle *handle, + u8 proc_id) +{ + struct ti_sci_msg_req_proc_request *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (!handle) + return -EINVAL; + if (IS_ERR(handle)) + return PTR_ERR(handle); + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PROC_REQUEST, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_proc_request *)xfer->xfer_buf; + req->processor_id = proc_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_proc_release() - Command to release a physical processor control + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_proc_release(const struct ti_sci_handle *handle, + u8 proc_id) +{ + struct ti_sci_msg_req_proc_release *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (!handle) + return -EINVAL; + if (IS_ERR(handle)) + return PTR_ERR(handle); + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PROC_RELEASE, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_proc_release *)xfer->xfer_buf; + req->processor_id = proc_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_proc_handover() - Command to handover a physical processor + * control to a host in the processor's access + * control list. + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * @host_id: Host ID to get the control of the processor + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_proc_handover(const struct ti_sci_handle *handle, + u8 proc_id, u8 host_id) +{ + struct ti_sci_msg_req_proc_handover *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (!handle) + return -EINVAL; + if (IS_ERR(handle)) + return PTR_ERR(handle); + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PROC_HANDOVER, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_proc_handover *)xfer->xfer_buf; + req->processor_id = proc_id; + req->host_id = host_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_proc_set_config() - Command to set the processor boot + * configuration flags + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * @config_flags_set: Configuration flags to be set + * @config_flags_clear: Configuration flags to be cleared. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_proc_set_config(const struct ti_sci_handle *handle, + u8 proc_id, u64 bootvector, + u32 config_flags_set, + u32 config_flags_clear) +{ + struct ti_sci_msg_req_set_config *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (!handle) + return -EINVAL; + if (IS_ERR(handle)) + return PTR_ERR(handle); + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CONFIG, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_set_config *)xfer->xfer_buf; + req->processor_id = proc_id; + req->bootvector_low = bootvector & TI_SCI_ADDR_LOW_MASK; + req->bootvector_high = (bootvector & TI_SCI_ADDR_HIGH_MASK) >> + TI_SCI_ADDR_HIGH_SHIFT; + req->config_flags_set = config_flags_set; + req->config_flags_clear = config_flags_clear; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_proc_set_control() - Command to set the processor boot + * control flags + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * @control_flags_set: Control flags to be set + * @control_flags_clear: Control flags to be cleared + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_proc_set_control(const struct ti_sci_handle *handle, + u8 proc_id, u32 control_flags_set, + u32 control_flags_clear) +{ + struct ti_sci_msg_req_set_ctrl *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (!handle) + return -EINVAL; + if (IS_ERR(handle)) + return PTR_ERR(handle); + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CTRL, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_set_ctrl *)xfer->xfer_buf; + req->processor_id = proc_id; + req->control_flags_set = control_flags_set; + req->control_flags_clear = control_flags_clear; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + +/** + * ti_sci_cmd_get_boot_status() - Command to get the processor boot status + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_proc_get_status(const struct ti_sci_handle *handle, + u8 proc_id, u64 *bv, u32 *cfg_flags, + u32 *ctrl_flags, u32 *sts_flags) +{ + struct ti_sci_msg_resp_get_status *resp; + struct ti_sci_msg_req_get_status *req; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (!handle) + return -EINVAL; + if (IS_ERR(handle)) + return PTR_ERR(handle); + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_STATUS, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_get_status *)xfer->xfer_buf; + req->processor_id = proc_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_resp_get_status *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) { + ret = -ENODEV; + } else { + *bv = (resp->bootvector_low & TI_SCI_ADDR_LOW_MASK) | + (((u64)resp->bootvector_high << TI_SCI_ADDR_HIGH_SHIFT) & + TI_SCI_ADDR_HIGH_MASK); + *cfg_flags = resp->config_flags; + *ctrl_flags = resp->control_flags; + *sts_flags = resp->status_flags; + } + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + /* * ti_sci_setup_ops() - Setup the operations structures * @info: pointer to TISCI pointer @@ -2494,6 +2836,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops; struct ti_sci_rm_psil_ops *psilops = &ops->rm_psil_ops; struct ti_sci_rm_udmap_ops *udmap_ops = &ops->rm_udmap_ops; + struct ti_sci_proc_ops *pops = &ops->proc_ops; core_ops->reboot_device = ti_sci_cmd_core_reboot; @@ -2543,6 +2886,13 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) udmap_ops->tx_ch_cfg = ti_sci_cmd_rm_udmap_tx_ch_cfg; udmap_ops->rx_ch_cfg = ti_sci_cmd_rm_udmap_rx_ch_cfg; udmap_ops->rx_flow_cfg = ti_sci_cmd_rm_udmap_rx_flow_cfg; + + pops->request = ti_sci_cmd_proc_request; + pops->release = ti_sci_cmd_proc_release; + pops->handover = ti_sci_cmd_proc_handover; + pops->set_config = ti_sci_cmd_proc_set_config; + pops->set_control = ti_sci_cmd_proc_set_control; + pops->get_status = ti_sci_cmd_proc_get_status; } /** diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 2bb81ec7793c..662dcffef311 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -71,6 +71,14 @@ #define TISCI_MSG_RM_UDMAP_FLOW_GET_CFG 0x1232 #define TISCI_MSG_RM_UDMAP_FLOW_SIZE_THRESH_GET_CFG 0x1233 +/* Processor Control requests */ +#define TI_SCI_MSG_PROC_REQUEST 0xc000 +#define TI_SCI_MSG_PROC_RELEASE 0xc001 +#define TI_SCI_MSG_PROC_HANDOVER 0xc005 +#define TI_SCI_MSG_SET_CONFIG 0xc100 +#define TI_SCI_MSG_SET_CTRL 0xc101 +#define TI_SCI_MSG_GET_STATUS 0xc400 + /** * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses * @type: Type of messages: One of TI_SCI_MSG* values @@ -1238,4 +1246,131 @@ struct ti_sci_msg_rm_udmap_flow_cfg_req { u8 rx_ps_location; } __packed; +/** + * struct ti_sci_msg_req_proc_request - Request a processor + * @hdr: Generic Header + * @processor_id: ID of processor being requested + * + * Request type is TI_SCI_MSG_PROC_REQUEST, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_proc_request { + struct ti_sci_msg_hdr hdr; + u8 processor_id; +} __packed; + +/** + * struct ti_sci_msg_req_proc_release - Release a processor + * @hdr: Generic Header + * @processor_id: ID of processor being released + * + * Request type is TI_SCI_MSG_PROC_RELEASE, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_proc_release { + struct ti_sci_msg_hdr hdr; + u8 processor_id; +} __packed; + +/** + * struct ti_sci_msg_req_proc_handover - Handover a processor to a host + * @hdr: Generic Header + * @processor_id: ID of processor being handed over + * @host_id: Host ID the control needs to be transferred to + * + * Request type is TI_SCI_MSG_PROC_HANDOVER, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_proc_handover { + struct ti_sci_msg_hdr hdr; + u8 processor_id; + u8 host_id; +} __packed; + +/* Boot Vector masks */ +#define TI_SCI_ADDR_LOW_MASK GENMASK_ULL(31, 0) +#define TI_SCI_ADDR_HIGH_MASK GENMASK_ULL(63, 32) +#define TI_SCI_ADDR_HIGH_SHIFT 32 + +/** + * struct ti_sci_msg_req_set_config - Set Processor boot configuration + * @hdr: Generic Header + * @processor_id: ID of processor being configured + * @bootvector_low: Lower 32 bit address (Little Endian) of boot vector + * @bootvector_high: Higher 32 bit address (Little Endian) of boot vector + * @config_flags_set: Optional Processor specific Config Flags to set. + * Setting a bit here implies the corresponding mode + * will be set + * @config_flags_clear: Optional Processor specific Config Flags to clear. + * Setting a bit here implies the corresponding mode + * will be cleared + * + * Request type is TI_SCI_MSG_PROC_HANDOVER, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_set_config { + struct ti_sci_msg_hdr hdr; + u8 processor_id; + u32 bootvector_low; + u32 bootvector_high; + u32 config_flags_set; + u32 config_flags_clear; +} __packed; + +/** + * struct ti_sci_msg_req_set_ctrl - Set Processor boot control flags + * @hdr: Generic Header + * @processor_id: ID of processor being configured + * @control_flags_set: Optional Processor specific Control Flags to set. + * Setting a bit here implies the corresponding mode + * will be set + * @control_flags_clear:Optional Processor specific Control Flags to clear. + * Setting a bit here implies the corresponding mode + * will be cleared + * + * Request type is TI_SCI_MSG_SET_CTRL, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_set_ctrl { + struct ti_sci_msg_hdr hdr; + u8 processor_id; + u32 control_flags_set; + u32 control_flags_clear; +} __packed; + +/** + * struct ti_sci_msg_req_get_status - Processor boot status request + * @hdr: Generic Header + * @processor_id: ID of processor whose status is being requested + * + * Request type is TI_SCI_MSG_GET_STATUS, response is an appropriate + * message, or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_get_status { + struct ti_sci_msg_hdr hdr; + u8 processor_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_status - Processor boot status response + * @hdr: Generic Header + * @processor_id: ID of processor whose status is returned + * @bootvector_low: Lower 32 bit address (Little Endian) of boot vector + * @bootvector_high: Higher 32 bit address (Little Endian) of boot vector + * @config_flags: Optional Processor specific Config Flags set currently + * @control_flags: Optional Processor specific Control Flags set currently + * @status_flags: Optional Processor specific Status Flags set currently + * + * Response structure to a TI_SCI_MSG_GET_STATUS request. + */ +struct ti_sci_msg_resp_get_status { + struct ti_sci_msg_hdr hdr; + u8 processor_id; + u32 bootvector_low; + u32 bootvector_high; + u32 config_flags; + u32 control_flags; + u32 status_flags; +} __packed; + #endif /* __TI_SCI_H */ diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index 4fd9bff5806b..7b3762f68df9 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -453,12 +453,42 @@ struct ti_sci_rm_udmap_ops { const struct ti_sci_msg_rm_udmap_flow_cfg *params); }; +/** + * struct ti_sci_proc_ops - Processor Control operations + * @request: Request to control a physical processor. The requesting host + * should be in the processor access list + * @release: Relinquish a physical processor control + * @handover: Handover a physical processor control to another host + * in the permitted list + * @set_config: Set base configuration of a processor + * @set_control: Setup limited control flags in specific cases + * @get_status: Get the state of physical processor + * + * NOTE: The following paramteres are generic in nature for all these ops, + * -handle: Pointer to TI SCI handle as retrieved by *ti_sci_get_handle + * -pid: Processor ID + * -hid: Host ID + */ +struct ti_sci_proc_ops { + int (*request)(const struct ti_sci_handle *handle, u8 pid); + int (*release)(const struct ti_sci_handle *handle, u8 pid); + int (*handover)(const struct ti_sci_handle *handle, u8 pid, u8 hid); + int (*set_config)(const struct ti_sci_handle *handle, u8 pid, + u64 boot_vector, u32 cfg_set, u32 cfg_clr); + int (*set_control)(const struct ti_sci_handle *handle, u8 pid, + u32 ctrl_set, u32 ctrl_clr); + int (*get_status)(const struct ti_sci_handle *handle, u8 pid, + u64 *boot_vector, u32 *cfg_flags, u32 *ctrl_flags, + u32 *status_flags); +}; + /** * struct ti_sci_ops - Function support for TI SCI * @dev_ops: Device specific operations * @clk_ops: Clock specific operations * @rm_core_ops: Resource management core operations. * @rm_irq_ops: IRQ management specific operations + * @proc_ops: Processor Control specific operations */ struct ti_sci_ops { struct ti_sci_core_ops core_ops; @@ -469,6 +499,7 @@ struct ti_sci_ops { struct ti_sci_rm_ringacc_ops rm_ring_ops; struct ti_sci_rm_psil_ops rm_psil_ops; struct ti_sci_rm_udmap_ops rm_udmap_ops; + struct ti_sci_proc_ops proc_ops; }; /** -- cgit v1.2.3 From 5ec47cda74e98ad2f723f93b4a97ba87638338aa Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 3 Jun 2019 17:12:33 +0900 Subject: memory: move jedec_ddr.h from include/memory to drivers/memory/ Now that jedec_ddr_data.c was moved from lib/ to drivers/memory/, is included only from drivers/memory/. Make it a local header of drivers/memory/. The directory include/memory is now gone. While I am here, I also changed #include to . Because CONFIG_DDR is bool, jedec_ddr_data.c is never compiled as a module. Signed-off-by: Masahiro Yamada Signed-off-by: Olof Johansson --- drivers/memory/emif.c | 3 +- drivers/memory/jedec_ddr.h | 175 ++++++++++++++++++++++++++++++++++++++++ drivers/memory/jedec_ddr_data.c | 5 +- drivers/memory/of_memory.c | 3 +- include/memory/jedec_ddr.h | 175 ---------------------------------------- 5 files changed, 182 insertions(+), 179 deletions(-) create mode 100644 drivers/memory/jedec_ddr.h delete mode 100644 include/memory/jedec_ddr.h (limited to 'include') diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index 2f214440008c..32cad7540d78 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -26,8 +26,9 @@ #include #include #include -#include + #include "emif.h" +#include "jedec_ddr.h" #include "of_memory.h" /** diff --git a/drivers/memory/jedec_ddr.h b/drivers/memory/jedec_ddr.h new file mode 100644 index 000000000000..a2094a9a588e --- /dev/null +++ b/drivers/memory/jedec_ddr.h @@ -0,0 +1,175 @@ +/* + * Definitions for DDR memories based on JEDEC specs + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * Aneesh V + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __JEDEC_DDR_H +#define __JEDEC_DDR_H + +#include + +/* DDR Densities */ +#define DDR_DENSITY_64Mb 1 +#define DDR_DENSITY_128Mb 2 +#define DDR_DENSITY_256Mb 3 +#define DDR_DENSITY_512Mb 4 +#define DDR_DENSITY_1Gb 5 +#define DDR_DENSITY_2Gb 6 +#define DDR_DENSITY_4Gb 7 +#define DDR_DENSITY_8Gb 8 +#define DDR_DENSITY_16Gb 9 +#define DDR_DENSITY_32Gb 10 + +/* DDR type */ +#define DDR_TYPE_DDR2 1 +#define DDR_TYPE_DDR3 2 +#define DDR_TYPE_LPDDR2_S4 3 +#define DDR_TYPE_LPDDR2_S2 4 +#define DDR_TYPE_LPDDR2_NVM 5 + +/* DDR IO width */ +#define DDR_IO_WIDTH_4 1 +#define DDR_IO_WIDTH_8 2 +#define DDR_IO_WIDTH_16 3 +#define DDR_IO_WIDTH_32 4 + +/* Number of Row bits */ +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 +#define R16 16 + +/* Number of Column bits */ +#define C7 7 +#define C8 8 +#define C9 9 +#define C10 10 +#define C11 11 +#define C12 12 + +/* Number of Banks */ +#define B1 0 +#define B2 1 +#define B4 2 +#define B8 3 + +/* Refresh rate in nano-seconds */ +#define T_REFI_15_6 15600 +#define T_REFI_7_8 7800 +#define T_REFI_3_9 3900 + +/* tRFC values */ +#define T_RFC_90 90000 +#define T_RFC_110 110000 +#define T_RFC_130 130000 +#define T_RFC_160 160000 +#define T_RFC_210 210000 +#define T_RFC_300 300000 +#define T_RFC_350 350000 + +/* Mode register numbers */ +#define DDR_MR0 0 +#define DDR_MR1 1 +#define DDR_MR2 2 +#define DDR_MR3 3 +#define DDR_MR4 4 +#define DDR_MR5 5 +#define DDR_MR6 6 +#define DDR_MR7 7 +#define DDR_MR8 8 +#define DDR_MR9 9 +#define DDR_MR10 10 +#define DDR_MR11 11 +#define DDR_MR16 16 +#define DDR_MR17 17 +#define DDR_MR18 18 + +/* + * LPDDR2 related defines + */ + +/* MR4 register fields */ +#define MR4_SDRAM_REF_RATE_SHIFT 0 +#define MR4_SDRAM_REF_RATE_MASK 7 +#define MR4_TUF_SHIFT 7 +#define MR4_TUF_MASK (1 << 7) + +/* MR4 SDRAM Refresh Rate field values */ +#define SDRAM_TEMP_NOMINAL 0x3 +#define SDRAM_TEMP_RESERVED_4 0x4 +#define SDRAM_TEMP_HIGH_DERATE_REFRESH 0x5 +#define SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS 0x6 +#define SDRAM_TEMP_VERY_HIGH_SHUTDOWN 0x7 + +#define NUM_DDR_ADDR_TABLE_ENTRIES 11 +#define NUM_DDR_TIMING_TABLE_ENTRIES 4 + +/* Structure for DDR addressing info from the JEDEC spec */ +struct lpddr2_addressing { + u32 num_banks; + u32 tREFI_ns; + u32 tRFCab_ps; +}; + +/* + * Structure for timings from the LPDDR2 datasheet + * All parameters are in pico seconds(ps) unless explicitly indicated + * with a suffix like tRAS_max_ns below + */ +struct lpddr2_timings { + u32 max_freq; + u32 min_freq; + u32 tRPab; + u32 tRCD; + u32 tWR; + u32 tRAS_min; + u32 tRRD; + u32 tWTR; + u32 tXP; + u32 tRTP; + u32 tCKESR; + u32 tDQSCK_max; + u32 tDQSCK_max_derated; + u32 tFAW; + u32 tZQCS; + u32 tZQCL; + u32 tZQinit; + u32 tRAS_max_ns; +}; + +/* + * Min value for some parameters in terms of number of tCK cycles(nCK) + * Please set to zero parameters that are not valid for a given memory + * type + */ +struct lpddr2_min_tck { + u32 tRPab; + u32 tRCD; + u32 tWR; + u32 tRASmin; + u32 tRRD; + u32 tWTR; + u32 tXP; + u32 tRTP; + u32 tCKE; + u32 tCKESR; + u32 tFAW; +}; + +extern const struct lpddr2_addressing + lpddr2_jedec_addressing_table[NUM_DDR_ADDR_TABLE_ENTRIES]; +extern const struct lpddr2_timings + lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES]; +extern const struct lpddr2_min_tck lpddr2_jedec_min_tck; + +#endif /* __JEDEC_DDR_H */ diff --git a/drivers/memory/jedec_ddr_data.c b/drivers/memory/jedec_ddr_data.c index 6d2cbf1d567f..1f9ca0f23407 100644 --- a/drivers/memory/jedec_ddr_data.c +++ b/drivers/memory/jedec_ddr_data.c @@ -10,8 +10,9 @@ * published by the Free Software Foundation. */ -#include -#include +#include + +#include "jedec_ddr.h" /* LPDDR2 addressing details from JESD209-2 section 2.4 */ const struct lpddr2_addressing diff --git a/drivers/memory/of_memory.c b/drivers/memory/of_memory.c index 12a61f558644..46539b27a3fb 100644 --- a/drivers/memory/of_memory.c +++ b/drivers/memory/of_memory.c @@ -10,8 +10,9 @@ #include #include #include -#include #include + +#include "jedec_ddr.h" #include "of_memory.h" /** diff --git a/include/memory/jedec_ddr.h b/include/memory/jedec_ddr.h deleted file mode 100644 index ddad0f870e5d..000000000000 --- a/include/memory/jedec_ddr.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Definitions for DDR memories based on JEDEC specs - * - * Copyright (C) 2012 Texas Instruments, Inc. - * - * Aneesh V - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef __LINUX_JEDEC_DDR_H -#define __LINUX_JEDEC_DDR_H - -#include - -/* DDR Densities */ -#define DDR_DENSITY_64Mb 1 -#define DDR_DENSITY_128Mb 2 -#define DDR_DENSITY_256Mb 3 -#define DDR_DENSITY_512Mb 4 -#define DDR_DENSITY_1Gb 5 -#define DDR_DENSITY_2Gb 6 -#define DDR_DENSITY_4Gb 7 -#define DDR_DENSITY_8Gb 8 -#define DDR_DENSITY_16Gb 9 -#define DDR_DENSITY_32Gb 10 - -/* DDR type */ -#define DDR_TYPE_DDR2 1 -#define DDR_TYPE_DDR3 2 -#define DDR_TYPE_LPDDR2_S4 3 -#define DDR_TYPE_LPDDR2_S2 4 -#define DDR_TYPE_LPDDR2_NVM 5 - -/* DDR IO width */ -#define DDR_IO_WIDTH_4 1 -#define DDR_IO_WIDTH_8 2 -#define DDR_IO_WIDTH_16 3 -#define DDR_IO_WIDTH_32 4 - -/* Number of Row bits */ -#define R9 9 -#define R10 10 -#define R11 11 -#define R12 12 -#define R13 13 -#define R14 14 -#define R15 15 -#define R16 16 - -/* Number of Column bits */ -#define C7 7 -#define C8 8 -#define C9 9 -#define C10 10 -#define C11 11 -#define C12 12 - -/* Number of Banks */ -#define B1 0 -#define B2 1 -#define B4 2 -#define B8 3 - -/* Refresh rate in nano-seconds */ -#define T_REFI_15_6 15600 -#define T_REFI_7_8 7800 -#define T_REFI_3_9 3900 - -/* tRFC values */ -#define T_RFC_90 90000 -#define T_RFC_110 110000 -#define T_RFC_130 130000 -#define T_RFC_160 160000 -#define T_RFC_210 210000 -#define T_RFC_300 300000 -#define T_RFC_350 350000 - -/* Mode register numbers */ -#define DDR_MR0 0 -#define DDR_MR1 1 -#define DDR_MR2 2 -#define DDR_MR3 3 -#define DDR_MR4 4 -#define DDR_MR5 5 -#define DDR_MR6 6 -#define DDR_MR7 7 -#define DDR_MR8 8 -#define DDR_MR9 9 -#define DDR_MR10 10 -#define DDR_MR11 11 -#define DDR_MR16 16 -#define DDR_MR17 17 -#define DDR_MR18 18 - -/* - * LPDDR2 related defines - */ - -/* MR4 register fields */ -#define MR4_SDRAM_REF_RATE_SHIFT 0 -#define MR4_SDRAM_REF_RATE_MASK 7 -#define MR4_TUF_SHIFT 7 -#define MR4_TUF_MASK (1 << 7) - -/* MR4 SDRAM Refresh Rate field values */ -#define SDRAM_TEMP_NOMINAL 0x3 -#define SDRAM_TEMP_RESERVED_4 0x4 -#define SDRAM_TEMP_HIGH_DERATE_REFRESH 0x5 -#define SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS 0x6 -#define SDRAM_TEMP_VERY_HIGH_SHUTDOWN 0x7 - -#define NUM_DDR_ADDR_TABLE_ENTRIES 11 -#define NUM_DDR_TIMING_TABLE_ENTRIES 4 - -/* Structure for DDR addressing info from the JEDEC spec */ -struct lpddr2_addressing { - u32 num_banks; - u32 tREFI_ns; - u32 tRFCab_ps; -}; - -/* - * Structure for timings from the LPDDR2 datasheet - * All parameters are in pico seconds(ps) unless explicitly indicated - * with a suffix like tRAS_max_ns below - */ -struct lpddr2_timings { - u32 max_freq; - u32 min_freq; - u32 tRPab; - u32 tRCD; - u32 tWR; - u32 tRAS_min; - u32 tRRD; - u32 tWTR; - u32 tXP; - u32 tRTP; - u32 tCKESR; - u32 tDQSCK_max; - u32 tDQSCK_max_derated; - u32 tFAW; - u32 tZQCS; - u32 tZQCL; - u32 tZQinit; - u32 tRAS_max_ns; -}; - -/* - * Min value for some parameters in terms of number of tCK cycles(nCK) - * Please set to zero parameters that are not valid for a given memory - * type - */ -struct lpddr2_min_tck { - u32 tRPab; - u32 tRCD; - u32 tWR; - u32 tRASmin; - u32 tRRD; - u32 tWTR; - u32 tXP; - u32 tRTP; - u32 tCKE; - u32 tCKESR; - u32 tFAW; -}; - -extern const struct lpddr2_addressing - lpddr2_jedec_addressing_table[NUM_DDR_ADDR_TABLE_ENTRIES]; -extern const struct lpddr2_timings - lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES]; -extern const struct lpddr2_min_tck lpddr2_jedec_min_tck; - -#endif /* __LINUX_JEDEC_DDR_H */ -- cgit v1.2.3