diff options
author | Jani Nikula <jani.nikula@intel.com> | 2020-06-25 18:05:03 +0300 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2020-06-25 18:05:03 +0300 |
commit | 0f69403d2535ffc7200a8414cf3ca66a49b0d741 (patch) | |
tree | 3ce85dd08359ea872aa8fb9bd12072efdb80a787 /drivers/char | |
parent | 580fbdc5136822208f107500682e50a1cb232e94 (diff) | |
parent | 0a19b068acc47d05212f03e494381926dc0381e2 (diff) |
Merge drm/drm-next into drm-intel-next-queued
Catch up with upstream, in particular to get c1e8d7c6a7a6 ("mmap locking
API: convert mmap_sem comments").
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Diffstat (limited to 'drivers/char')
36 files changed, 1117 insertions, 226 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index d4665fe9ccd2..98c3a5d8003e 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -11,7 +11,7 @@ config TTY_PRINTK tristate "TTY driver to output user messages via printk" depends on EXPERT && TTY default n - ---help--- + help If you say Y here, the support for writing user messages (i.e. console messages) via printk is available. @@ -33,7 +33,7 @@ config TTY_PRINTK_LEVEL config PRINTER tristate "Parallel printer support" depends on PARPORT - ---help--- + help If you intend to attach a printer to the parallel port of your Linux box (as opposed to using a serial printer; if the connector at the printer has 9 or 25 holes ["female"], then it's serial), say Y. @@ -59,7 +59,7 @@ config PRINTER config LP_CONSOLE bool "Support for console on line printer" depends on PRINTER - ---help--- + help If you want kernel messages to be printed out as they occur, you can have a console on the printer. This option adds support for doing that; to actually get it to happen you need to pass the @@ -76,7 +76,7 @@ config LP_CONSOLE config PPDEV tristate "Support for user-space parallel port device drivers" depends on PARPORT - ---help--- + help Saying Y to this adds support for /dev/parport device nodes. This is needed for programs that want portable access to the parallel port, for instance deviceid (which displays Plug-and-Play device @@ -146,7 +146,7 @@ config DS1620 config NWBUTTON tristate "NetWinder Button" depends on ARCH_NETWINDER - ---help--- + help If you say Y here and create a character device node /dev/nwbutton with major and minor numbers 10 and 158 ("man mknod"), then every time the orange button is pressed a number of times, the number of @@ -182,7 +182,7 @@ config NWBUTTON_REBOOT config NWFLASH tristate "NetWinder flash support" depends on ARCH_NETWINDER - ---help--- + help If you say Y here and create a character device /dev/flash with major 10 and minor 160 you can manipulate the flash ROM containing the NetWinder firmware. Be careful as accidentally overwriting the @@ -209,7 +209,7 @@ config DTLK config XILINX_HWICAP tristate "Xilinx HWICAP Support" - depends on XILINX_VIRTEX || MICROBLAZE + depends on MICROBLAZE help This option enables support for Xilinx Internal Configuration Access Port (ICAP) driver. The ICAP is used on Xilinx Virtex @@ -220,7 +220,7 @@ config XILINX_HWICAP config R3964 tristate "Siemens R3964 line discipline" depends on TTY && BROKEN - ---help--- + help This driver allows synchronous communication with devices using the Siemens R3964 packet protocol. Unless you are dealing with special hardware like PLCs, you are unlikely to need this. @@ -233,7 +233,7 @@ config R3964 config APPLICOM tristate "Applicom intelligent fieldbus card support" depends on PCI - ---help--- + help This driver provides the kernel-side support for the intelligent fieldbus cards made by Applicom International. More information about these cards can be found on the WWW at the address @@ -248,7 +248,7 @@ config APPLICOM config SONYPI tristate "Sony Vaio Programmable I/O Control Device support" depends on X86_32 && PCI && INPUT - ---help--- + help This driver enables access to the Sony Programmable I/O Control Device which can be found in many (all ?) Sony Vaio laptops. @@ -269,7 +269,7 @@ config MWAVE tristate "ACP Modem (Mwave) support" depends on X86 && TTY select SERIAL_8250 - ---help--- + help The ACP modem (Mwave) for Linux is a WinModem. It is composed of a kernel driver and a user level application. Together these components support direct attachment to public switched telephone networks (PSTNs) @@ -347,7 +347,7 @@ config NVRAM tristate "/dev/nvram support" depends on X86 || HAVE_ARCH_NVRAM_OPS default M68K || PPC - ---help--- + help If you say Y here and create a character special file /dev/nvram with major number 10 and minor number 144 using mknod ("man mknod"), you get read and write access to the non-volatile memory. diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index bc54235a7022..a086dd34f932 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -3,7 +3,7 @@ menuconfig AGP tristate "/dev/agpgart (AGP Support)" depends on ALPHA || IA64 || PARISC || PPC || X86 depends on PCI - ---help--- + help AGP (Accelerated Graphics Port) is a bus system mainly used to connect graphics cards to the rest of the system. @@ -30,7 +30,7 @@ menuconfig AGP config AGP_ALI tristate "ALI chipset support" depends on AGP && X86_32 - ---help--- + help This option gives you AGP support for the GLX component of X on the following ALi chipsets. The supported chipsets include M1541, M1621, M1631, M1632, M1641,M1647,and M1651. @@ -45,7 +45,7 @@ config AGP_ALI config AGP_ATI tristate "ATI chipset support" depends on AGP && X86_32 - ---help--- + help This option gives you AGP support for the GLX component of X on the ATI RadeonIGP family of chipsets. diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index 47098648502d..00ff5fcb808a 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -39,7 +39,6 @@ #include <linux/fs.h> #include <linux/sched.h> #include <linux/uaccess.h> -#include <asm/pgtable.h> #include "agp.h" struct agp_front_data agp_fe; diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 9e84239f88d4..3ffbb1c80c5c 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -42,7 +42,6 @@ #ifdef CONFIG_X86 #include <asm/set_memory.h> #endif -#include <asm/pgtable.h> #include "agp.h" __u32 *agp_gatt_table; diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index e5e5333f302d..cce2af5df7b4 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c @@ -17,7 +17,6 @@ #include <linux/list.h> #include <linux/mm.h> #include <linux/slab.h> -#include <asm/pgtable.h> #include <asm/io.h> /* diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 9bc46da8d77a..0ad17efc96df 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -6,7 +6,7 @@ menuconfig HW_RANDOM tristate "Hardware Random Number Generator Core support" default m - ---help--- + help Hardware Random Number Generator Core infrastructure. To compile this driver as a module, choose M here: the @@ -24,7 +24,7 @@ if HW_RANDOM config HW_RANDOM_TIMERIOMEM tristate "Timer IOMEM HW Random Number Generator support" depends on HAS_IOMEM - ---help--- + help This driver provides kernel-side support for a generic Random Number Generator used by reading a 'dumb' iomem address that is to be read no faster than, for example, once a second; @@ -39,7 +39,7 @@ config HW_RANDOM_INTEL tristate "Intel HW Random Number Generator support" depends on (X86 || IA64) && PCI default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on Intel i8xx-based motherboards. @@ -52,7 +52,7 @@ config HW_RANDOM_AMD tristate "AMD HW Random Number Generator support" depends on (X86 || PPC_MAPLE) && PCI default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on AMD 76x-based motherboards. @@ -65,7 +65,7 @@ config HW_RANDOM_ATMEL tristate "Atmel Random Number Generator support" depends on ARCH_AT91 && HAVE_CLK && OF default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on Atmel AT91 devices. @@ -79,7 +79,7 @@ config HW_RANDOM_BCM2835 depends on ARCH_BCM2835 || ARCH_BCM_NSP || ARCH_BCM_5301X || \ ARCH_BCM_63XX || BCM63XX || BMIPS_GENERIC default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on the Broadcom BCM2835 and BCM63xx SoCs. @@ -92,7 +92,7 @@ config HW_RANDOM_IPROC_RNG200 tristate "Broadcom iProc/STB RNG200 support" depends on ARCH_BCM_IPROC || ARCH_BCM2835 || ARCH_BRCMSTB default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the RNG200 hardware found on the Broadcom iProc and STB SoCs. @@ -105,7 +105,7 @@ config HW_RANDOM_GEODE tristate "AMD Geode HW Random Number Generator support" depends on X86_32 && PCI default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on the AMD Geode LX. @@ -118,7 +118,7 @@ config HW_RANDOM_N2RNG tristate "Niagara2 Random Number Generator support" depends on SPARC64 default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on Niagara2 cpus. @@ -131,7 +131,7 @@ config HW_RANDOM_VIA tristate "VIA HW Random Number Generator support" depends on X86 default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on VIA based motherboards. @@ -144,7 +144,7 @@ config HW_RANDOM_IXP4XX tristate "Intel IXP4xx NPU HW Pseudo-Random Number Generator support" depends on ARCH_IXP4XX default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Pseudo-Random Number Generator hardware found on the Intel IXP45x/46x NPU. @@ -157,7 +157,7 @@ config HW_RANDOM_OMAP tristate "OMAP Random Number Generator support" depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS || ARCH_MVEBU default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on OMAP16xx, OMAP2/3/4/5, AM33xx/AM43xx multimedia processors, and Marvell Armada 7k/8k SoCs. @@ -171,7 +171,7 @@ config HW_RANDOM_OMAP3_ROM tristate "OMAP3 ROM Random Number Generator support" depends on ARCH_OMAP3 default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on OMAP34xx processors. @@ -184,7 +184,7 @@ config HW_RANDOM_OCTEON tristate "Octeon Random Number Generator support" depends on CAVIUM_OCTEON_SOC default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on Octeon processors. @@ -197,7 +197,7 @@ config HW_RANDOM_PASEMI tristate "PA Semi HW Random Number Generator support" depends on PPC_PASEMI default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on PA Semi PWRficient SoCs. @@ -209,7 +209,7 @@ config HW_RANDOM_PASEMI config HW_RANDOM_VIRTIO tristate "VirtIO Random Number Generator support" depends on VIRTIO - ---help--- + help This driver provides kernel-side support for the virtual Random Number Generator hardware. @@ -220,7 +220,7 @@ config HW_RANDOM_TX4939 tristate "TX4939 Random Number Generator support" depends on SOC_TX4939 default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on TX4939 SoC. @@ -233,7 +233,7 @@ config HW_RANDOM_MXC_RNGA tristate "Freescale i.MX RNGA Random Number Generator" depends on SOC_IMX31 default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on Freescale i.MX processors. @@ -247,7 +247,7 @@ config HW_RANDOM_IMX_RNGC depends on HAS_IOMEM && HAVE_CLK depends on SOC_IMX25 || COMPILE_TEST default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator Version C hardware found on some Freescale i.MX processors. Version B is also supported by this driver. @@ -261,7 +261,7 @@ config HW_RANDOM_NOMADIK tristate "ST-Ericsson Nomadik Random Number Generator support" depends on ARCH_NOMADIK default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on ST-Ericsson SoCs (8815 and 8500). @@ -274,7 +274,7 @@ config HW_RANDOM_PSERIES tristate "pSeries HW Random Number Generator support" depends on PPC64 && IBMVIO default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on POWER7+ machines and above @@ -287,7 +287,7 @@ config HW_RANDOM_POWERNV tristate "PowerNV Random Number Generator support" depends on PPC_POWERNV default HW_RANDOM - ---help--- + help This is the driver for Random Number Generator hardware found in POWER7+ and above machines for PowerNV platform. @@ -300,7 +300,7 @@ config HW_RANDOM_HISI tristate "Hisilicon Random Number Generator support" depends on HW_RANDOM && ARCH_HISI default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on Hisilicon Hip04 and Hip05 SoC. @@ -325,7 +325,7 @@ config HW_RANDOM_HISI_V2 config HW_RANDOM_ST tristate "ST Microelectronics HW Random Number Generator support" depends on HW_RANDOM && ARCH_STI - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on STi series of SoCs. @@ -336,7 +336,7 @@ config HW_RANDOM_XGENE tristate "APM X-Gene True Random Number Generator (TRNG) support" depends on HW_RANDOM && ARCH_XGENE default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on APM X-Gene SoC. @@ -363,7 +363,7 @@ config HW_RANDOM_PIC32 tristate "Microchip PIC32 Random Number Generator support" depends on HW_RANDOM && MACH_PIC32 default y - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on a PIC32. @@ -377,7 +377,7 @@ config HW_RANDOM_MESON depends on HW_RANDOM depends on ARCH_MESON || COMPILE_TEST default y - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on Amlogic Meson SoCs. @@ -390,7 +390,7 @@ config HW_RANDOM_CAVIUM tristate "Cavium ThunderX Random Number Generator support" depends on HW_RANDOM && PCI && (ARM64 || (COMPILE_TEST && 64BIT)) default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on Cavium SoCs. @@ -404,7 +404,7 @@ config HW_RANDOM_MTK depends on HW_RANDOM depends on ARCH_MEDIATEK || COMPILE_TEST default y - ---help--- + help This driver provides kernel-side support for the Random Number Generator hardware found on Mediatek SoCs. @@ -417,7 +417,7 @@ config HW_RANDOM_S390 tristate "S390 True Random Number Generator support" depends on S390 default HW_RANDOM - ---help--- + help This driver provides kernel-side support for the True Random Number Generator available as CPACF extension on modern s390 hardware platforms. @@ -431,7 +431,7 @@ config HW_RANDOM_EXYNOS tristate "Samsung Exynos True Random Number Generator support" depends on ARCH_EXYNOS || COMPILE_TEST default HW_RANDOM - ---help--- + help This driver provides support for the True Random Number Generator available in Exynos SoCs. @@ -474,6 +474,19 @@ config HW_RANDOM_KEYSTONE help This option enables Keystone's hardware random generator. +config HW_RANDOM_CCTRNG + tristate "Arm CryptoCell True Random Number Generator support" + depends on HAS_IOMEM && OF + help + Say 'Y' to enable the True Random Number Generator driver for the + Arm TrustZone CryptoCell family of processors. + Currently the CryptoCell 713 and 703 are supported. + The driver is supported only in SoC where Trusted Execution + Environment is not used. + Choose 'M' to compile this driver as a module. The module + will be called cctrng. + If unsure, say 'N'. + endif # HW_RANDOM config UML_RANDOM diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index a7801b49ce6c..2c6724735345 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -41,3 +41,4 @@ obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o obj-$(CONFIG_HW_RANDOM_NPCM) += npcm-rng.o +obj-$(CONFIG_HW_RANDOM_CCTRNG) += cctrng.o diff --git a/drivers/char/hw_random/cctrng.c b/drivers/char/hw_random/cctrng.c new file mode 100644 index 000000000000..619148fb2dc9 --- /dev/null +++ b/drivers/char/hw_random/cctrng.c @@ -0,0 +1,735 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) 2019-2020 ARM Limited or its affiliates. */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/clk.h> +#include <linux/hw_random.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/interrupt.h> +#include <linux/irqreturn.h> +#include <linux/workqueue.h> +#include <linux/circ_buf.h> +#include <linux/completion.h> +#include <linux/of.h> +#include <linux/bitfield.h> +#include <linux/fips.h> + +#include "cctrng.h" + +#define CC_REG_LOW(name) (name ## _BIT_SHIFT) +#define CC_REG_HIGH(name) (CC_REG_LOW(name) + name ## _BIT_SIZE - 1) +#define CC_GENMASK(name) GENMASK(CC_REG_HIGH(name), CC_REG_LOW(name)) + +#define CC_REG_FLD_GET(reg_name, fld_name, reg_val) \ + (FIELD_GET(CC_GENMASK(CC_ ## reg_name ## _ ## fld_name), reg_val)) + +#define CC_HW_RESET_LOOP_COUNT 10 +#define CC_TRNG_SUSPEND_TIMEOUT 3000 + +/* data circular buffer in words must be: + * - of a power-of-2 size (limitation of circ_buf.h macros) + * - at least 6, the size generated in the EHR according to HW implementation + */ +#define CCTRNG_DATA_BUF_WORDS 32 + +/* The timeout for the TRNG operation should be calculated with the formula: + * Timeout = EHR_NUM * VN_COEFF * EHR_LENGTH * SAMPLE_CNT * SCALE_VALUE + * while: + * - SAMPLE_CNT is input value from the characterisation process + * - all the rest are constants + */ +#define EHR_NUM 1 +#define VN_COEFF 4 +#define EHR_LENGTH CC_TRNG_EHR_IN_BITS +#define SCALE_VALUE 2 +#define CCTRNG_TIMEOUT(smpl_cnt) \ + (EHR_NUM * VN_COEFF * EHR_LENGTH * smpl_cnt * SCALE_VALUE) + +struct cctrng_drvdata { + struct platform_device *pdev; + void __iomem *cc_base; + struct clk *clk; + struct hwrng rng; + u32 active_rosc; + /* Sampling interval for each ring oscillator: + * count of ring oscillator cycles between consecutive bits sampling. + * Value of 0 indicates non-valid rosc + */ + u32 smpl_ratio[CC_TRNG_NUM_OF_ROSCS]; + + u32 data_buf[CCTRNG_DATA_BUF_WORDS]; + struct circ_buf circ; + struct work_struct compwork; + struct work_struct startwork; + + /* pending_hw - 1 when HW is pending, 0 when it is idle */ + atomic_t pending_hw; + + /* protects against multiple concurrent consumers of data_buf */ + spinlock_t read_lock; +}; + + +/* functions for write/read CC registers */ +static inline void cc_iowrite(struct cctrng_drvdata *drvdata, u32 reg, u32 val) +{ + iowrite32(val, (drvdata->cc_base + reg)); +} +static inline u32 cc_ioread(struct cctrng_drvdata *drvdata, u32 reg) +{ + return ioread32(drvdata->cc_base + reg); +} + + +static int cc_trng_pm_get(struct device *dev) +{ + int rc = 0; + + rc = pm_runtime_get_sync(dev); + + /* pm_runtime_get_sync() can return 1 as a valid return code */ + return (rc == 1 ? 0 : rc); +} + +static void cc_trng_pm_put_suspend(struct device *dev) +{ + int rc = 0; + + pm_runtime_mark_last_busy(dev); + rc = pm_runtime_put_autosuspend(dev); + if (rc) + dev_err(dev, "pm_runtime_put_autosuspend returned %x\n", rc); +} + +static int cc_trng_pm_init(struct cctrng_drvdata *drvdata) +{ + struct device *dev = &(drvdata->pdev->dev); + + /* must be before the enabling to avoid redundant suspending */ + pm_runtime_set_autosuspend_delay(dev, CC_TRNG_SUSPEND_TIMEOUT); + pm_runtime_use_autosuspend(dev); + /* set us as active - note we won't do PM ops until cc_trng_pm_go()! */ + return pm_runtime_set_active(dev); +} + +static void cc_trng_pm_go(struct cctrng_drvdata *drvdata) +{ + struct device *dev = &(drvdata->pdev->dev); + + /* enable the PM module*/ + pm_runtime_enable(dev); +} + +static void cc_trng_pm_fini(struct cctrng_drvdata *drvdata) +{ + struct device *dev = &(drvdata->pdev->dev); + + pm_runtime_disable(dev); +} + + +static inline int cc_trng_parse_sampling_ratio(struct cctrng_drvdata *drvdata) +{ + struct device *dev = &(drvdata->pdev->dev); + struct device_node *np = drvdata->pdev->dev.of_node; + int rc; + int i; + /* ret will be set to 0 if at least one rosc has (sampling ratio > 0) */ + int ret = -EINVAL; + + rc = of_property_read_u32_array(np, "arm,rosc-ratio", + drvdata->smpl_ratio, + CC_TRNG_NUM_OF_ROSCS); + if (rc) { + /* arm,rosc-ratio was not found in device tree */ + return rc; + } + + /* verify that at least one rosc has (sampling ratio > 0) */ + for (i = 0; i < CC_TRNG_NUM_OF_ROSCS; ++i) { + dev_dbg(dev, "rosc %d sampling ratio %u", + i, drvdata->smpl_ratio[i]); + + if (drvdata->smpl_ratio[i] > 0) + ret = 0; + } + + return ret; +} + +static int cc_trng_change_rosc(struct cctrng_drvdata *drvdata) +{ + struct device *dev = &(drvdata->pdev->dev); + + dev_dbg(dev, "cctrng change rosc (was %d)\n", drvdata->active_rosc); + drvdata->active_rosc += 1; + + while (drvdata->active_rosc < CC_TRNG_NUM_OF_ROSCS) { + if (drvdata->smpl_ratio[drvdata->active_rosc] > 0) + return 0; + + drvdata->active_rosc += 1; + } + return -EINVAL; +} + + +static void cc_trng_enable_rnd_source(struct cctrng_drvdata *drvdata) +{ + u32 max_cycles; + + /* Set watchdog threshold to maximal allowed time (in CPU cycles) */ + max_cycles = CCTRNG_TIMEOUT(drvdata->smpl_ratio[drvdata->active_rosc]); + cc_iowrite(drvdata, CC_RNG_WATCHDOG_VAL_REG_OFFSET, max_cycles); + + /* enable the RND source */ + cc_iowrite(drvdata, CC_RND_SOURCE_ENABLE_REG_OFFSET, 0x1); + + /* unmask RNG interrupts */ + cc_iowrite(drvdata, CC_RNG_IMR_REG_OFFSET, (u32)~CC_RNG_INT_MASK); +} + + +/* increase circular data buffer index (head/tail) */ +static inline void circ_idx_inc(int *idx, int bytes) +{ + *idx += (bytes + 3) >> 2; + *idx &= (CCTRNG_DATA_BUF_WORDS - 1); +} + +static inline size_t circ_buf_space(struct cctrng_drvdata *drvdata) +{ + return CIRC_SPACE(drvdata->circ.head, + drvdata->circ.tail, CCTRNG_DATA_BUF_WORDS); + +} + +static int cctrng_read(struct hwrng *rng, void *data, size_t max, bool wait) +{ + /* current implementation ignores "wait" */ + + struct cctrng_drvdata *drvdata = (struct cctrng_drvdata *)rng->priv; + struct device *dev = &(drvdata->pdev->dev); + u32 *buf = (u32 *)drvdata->circ.buf; + size_t copied = 0; + size_t cnt_w; + size_t size; + size_t left; + + if (!spin_trylock(&drvdata->read_lock)) { + /* concurrent consumers from data_buf cannot be served */ + dev_dbg_ratelimited(dev, "unable to hold lock\n"); + return 0; + } + + /* copy till end of data buffer (without wrap back) */ + cnt_w = CIRC_CNT_TO_END(drvdata->circ.head, + drvdata->circ.tail, CCTRNG_DATA_BUF_WORDS); + size = min((cnt_w<<2), max); + memcpy(data, &(buf[drvdata->circ.tail]), size); + copied = size; + circ_idx_inc(&drvdata->circ.tail, size); + /* copy rest of data in data buffer */ + left = max - copied; + if (left > 0) { + cnt_w = CIRC_CNT(drvdata->circ.head, + drvdata->circ.tail, CCTRNG_DATA_BUF_WORDS); + size = min((cnt_w<<2), left); + memcpy(data, &(buf[drvdata->circ.tail]), size); + copied += size; + circ_idx_inc(&drvdata->circ.tail, size); + } + + spin_unlock(&drvdata->read_lock); + + if (circ_buf_space(drvdata) >= CC_TRNG_EHR_IN_WORDS) { + if (atomic_cmpxchg(&drvdata->pending_hw, 0, 1) == 0) { + /* re-check space in buffer to avoid potential race */ + if (circ_buf_space(drvdata) >= CC_TRNG_EHR_IN_WORDS) { + /* increment device's usage counter */ + int rc = cc_trng_pm_get(dev); + + if (rc) { + dev_err(dev, + "cc_trng_pm_get returned %x\n", + rc); + return rc; + } + + /* schedule execution of deferred work handler + * for filling of data buffer + */ + schedule_work(&drvdata->startwork); + } else { + atomic_set(&drvdata->pending_hw, 0); + } + } + } + + return copied; +} + +static void cc_trng_hw_trigger(struct cctrng_drvdata *drvdata) +{ + u32 tmp_smpl_cnt = 0; + struct device *dev = &(drvdata->pdev->dev); + + dev_dbg(dev, "cctrng hw trigger.\n"); + + /* enable the HW RND clock */ + cc_iowrite(drvdata, CC_RNG_CLK_ENABLE_REG_OFFSET, 0x1); + + /* do software reset */ + cc_iowrite(drvdata, CC_RNG_SW_RESET_REG_OFFSET, 0x1); + /* in order to verify that the reset has completed, + * the sample count need to be verified + */ + do { + /* enable the HW RND clock */ + cc_iowrite(drvdata, CC_RNG_CLK_ENABLE_REG_OFFSET, 0x1); + + /* set sampling ratio (rng_clocks) between consecutive bits */ |