diff options
author | Jason M. Bills <jason.m.bills@linux.intel.com> | 2020-12-08 00:45:20 +0300 |
---|---|---|
committer | Jason M. Bills <jason.m.bills@linux.intel.com> | 2020-12-10 01:15:05 +0300 |
commit | 82dbc15a05125a812c140a3c8cff81c366482229 (patch) | |
tree | 9c8f1ad262a2e281f20340cf8646aca6f8596044 /meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch | |
parent | 8d6ae7f2a817751fad151168fa10ce28ee0869d8 (diff) | |
download | openbmc-82dbc15a05125a812c140a3c8cff81c366482229.tar.xz |
Update to internal 0.26
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch | 1780 |
1 files changed, 0 insertions, 1780 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch deleted file mode 100644 index d29098459..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch +++ /dev/null @@ -1,1780 +0,0 @@ -From e01c562db28797e3b6be9030f1f52507115c6765 Mon Sep 17 00:00:00 2001 -From: "Corona, Ernesto" <ernesto.corona@intel.com> -Date: Thu, 9 Jul 2020 12:03:34 -0700 -Subject: [PATCH] Add Aspeed SoC 24xx and 25xx families JTAG - -Driver adds support of Aspeed 2400-2600 series SOC JTAG master controller. - -Driver implements the following jtag ops: -- freq_get; -- freq_set; -- status_get; -- status_set -- xfer; -- mode_set; -- bitbang; -- enable; -- disable; - -It has been tested on Mellanox system with BMC equipped with -Aspeed 2520 SoC for programming CPLD devices. - -It has also been tested on Intel system using Aspeed 25xx SoC -for JTAG communication. - -Tested on Intel system using Aspeed 26xx SoC for JTAG communication. - -Signed-off-by: Oleksandr Shamray <oleksandrs@mellanox.com> -Signed-off-by: Jiri Pirko <jiri@mellanox.com> -Signed-off-by: Corona, Ernesto <ernesto.corona@intel.com> -Acked-by: Arnd Bergmann <arnd@arndb.de> -Acked-by: Philippe Ombredanne <pombredanne@nexb.com> -Acked-by: Joel Stanley <joel@jms.id.au> -Cc: Vadim Pasternak <vadimp@mellanox.com> -Cc: Andrew Jeffery <andrew@aj.id.au> -Cc: Steven A Filary <steven.a.filary@intel.com> -Cc: Bryan Hunt <bryan.hunt@intel.com> ---- -v29->v30 -Comments pointed by Steven Filary <steven.a.filary@intel.com> -- Add Suport for 26xx series - Software mode - Hardware mode 1 (disabled by default) - Hardware mode 2 (enabled by default) up to 160 bit lenght transfers -- clang jtag-aspeed.c - -v28->v29 -Comments pointed by Steven Filary <steven.a.filary@intel.com> -- Expand bitbang function to accept multiples bitbang operations within a - single JTAG_IOCBITBANG call. It will receive a buffer with TDI and TMS - values and it is expected that driver fills TDO fields with its - corresponding output value for every transaction. -- Always setup JTAG controller to master mode but disable JTAG output when - the driver is not in use to allow other HW to own the JTAG bus. Remove SCU - register accesses. This register controls the JTAG controller mode - (master/slave). -- Encansulate dev_dgb message into DEBUG_JTAG macros to improve driver's JTAG - performace. -- Add support for multichain. Set tap state and xfer operations now include - two tap state arguments: current state and end state. - -v27->v28 -Comments pointed by Steven Filary <steven.a.filary@intel.com> -- Replace JTAG_IOCRUNTEST with JTAG_SIOCSTATE adding support for all TAPC - end states in SW mode using a lookup table to navigate across states. -- Add support for simultaneous READ/WRITE transfers(JTAG_READ_WRITE_XFER). -- Support for switching JTAG controller mode between slave and master - mode. -- Setup JTAG controller mode to master only when the driver is opened, - letting other HW to own the JTAG bus when it isn't in use. -- Include JTAG bit bang IOCTL for low level JTAG control usage - (JTAG_IOCBITBANG). -- Add debug traces. -- Add support for register polling (default) due it is 3 times faster than - interrupt mode. Define USE_INTERRUPTS macro to enable interrupt usage. -- Remove unnecessary delays for aspeed_jtag_status_set function. It makes - SW mode 4 times faster. -- Clean data buffer on aspeed_jtag_xfer_sw before tdo writes to avoid data - output corruption for read operations in SW mode. -- Correct register settings for HW mode transfer operations. -- Propagate ret codes all the way from low level functions up to - JTAG_IOCXFER call. -- Support for partitioned transfers. Single JTAG transfer through - multiples JTAG_IOCXFER calls. Now end transmission(scan_end) also - evaluates transfer end state. - -v26->v27 -Changes made by Oleksandr Shamray <oleksandrs@mellamnox.com> -- change aspeed_jtag_sw_delay to udelay function in bit-bang operation - -v25->v26 -v24->v25 -Comments pointed by Greg KH <gregkh@linuxfoundation.org> -- reduced debug printouts - -v23->v24 -v22->v23 -v21->v22 -Comments pointed by Andy Shevchenko <andy.shevchenko@gmail.com> -- rearrange ASPEED register defines -- simplified JTAG divider calculation formula -- change delay function in bit-bang operation -- add helper functions for TAP states switching -- remove unnecessary comments -- remove redundant debug messages -- make dines for repetative register bit sets -- fixed indentation -- change checks from negative to positive -- add error check for clk_prepare_enable -- rework driver alloc/register to devm_ variant -- Increasing line length up to 85 in order to improve readability - -v20->v21 -v19->v20 -Notifications from kbuild test robot <lkp@intel.com> -- add static declaration to 'aspeed_jtag_init' and - 'aspeed_jtag_deinit' functions - -v18->v19 -v17->v18 -v16->v17 -v15->v16 -Comments pointed by Joel Stanley <joel.stan@gmail.com> -- Add reset_control on Jtag init/deinit - -v14->v15 -Comments pointed by Joel Stanley <joel.stan@gmail.com> -- Add ARCH_ASPEED || COMPILE_TEST to Kconfig -- remove unused offset variable -- remove "aspeed_jtag" from dev_err and dev_dbg messages -- change clk_prepare_enable initialisation order - -v13->v14 -Comments pointed by Philippe Ombredanne <pombredanne@nexb.com> -- Change style of head block comment from /**/ to // - -v12->v13 -Comments pointed by Philippe Ombredanne <pombredanne@nexb.com> -- Change jtag-aspeed.c licence type to - SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note - and reorder line with license- add reset descriptions in bndings file - in description -Comments pointed by Kun Yi <kunyi@google.com> -- Changed capability check for aspeed,ast2400-jtag/ast200-jtag - -v11->v12 -Comments pointed by Chip Bilbrey <chip@bilbrey.org> -- Remove access mode from xfer and idle transactions -- Add new ioctl JTAG_SIOCMODE for set hw mode - -v10->v11 -v9->v10 -V8->v9 -Comments pointed by Arnd Bergmann <arnd@arndb.de> -- add *data parameter to xfer function prototype - -v7->v8 -Comments pointed by Joel Stanley <joel.stan@gmail.com> -- aspeed_jtag_init replace goto to return; -- change input variables type from __u32 to u32 - in functios freq_get, freq_set, status_get -- change sm_ variables type from char to u8 -- in jatg_init add disable clocks on error case -- remove release_mem_region on error case -- remove devm_free_irq on jtag_deinit -- Fix misspelling Disabe/Disable -- Change compatible string to ast2400 and ast2000 - -v6->v7 -Notifications from kbuild test robot <lkp@intel.com> -- Add include <linux/types.h> to jtag-asapeed.c - -v5->v6 -v4->v5 -Comments pointed by Arnd Bergmann <arnd@arndb.de> -- Added HAS_IOMEM dependence in Kconfig to avoid - "undefined reference to `devm_ioremap_resource'" error, - because in some arch this not supported - -v3->v4 -Comments pointed by Arnd Bergmann <arnd@arndb.de> -- change transaction pointer tdio type to __u64 -- change internal status type from enum to __u32 - -v2->v3 - -v1->v2 -Comments pointed by Greg KH <gregkh@linuxfoundation.org> -- change license type from GPLv2/BSD to GPLv2 - -Comments pointed by Neil Armstrong <narmstrong@baylibre.com> -- Add clk_prepare_enable/clk_disable_unprepare in clock init/deinit -- Change .compatible to soc-specific compatible names - aspeed,aspeed4000-jtag/aspeed5000-jtag -- Added dt-bindings - -Comments pointed by Arnd Bergmann <arnd@arndb.de> -- Reorder functions and removed the forward declarations -- Add static const qualifier to state machine states transitions -- Change .compatible to soc-specific compatible names - aspeed,aspeed4000-jtag/aspeed5000-jtag -- Add dt-bindings - -Comments pointed by Randy Dunlap <rdunlap@infradead.org> -- Change module name jtag-aspeed in description in Kconfig - -Comments pointed by kbuild test robot <lkp@intel.com> -- Remove invalid include <asm/mach-types.h> -- add resource_size instead of calculation ---- - drivers/jtag/Kconfig | 14 + - drivers/jtag/Makefile | 1 + - drivers/jtag/jtag-aspeed.c | 1524 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 1539 insertions(+) - create mode 100644 drivers/jtag/jtag-aspeed.c - -diff --git a/drivers/jtag/Kconfig b/drivers/jtag/Kconfig -index 47771fc..0cc163f 100644 ---- a/drivers/jtag/Kconfig -+++ b/drivers/jtag/Kconfig -@@ -15,3 +15,17 @@ menuconfig JTAG - - To compile this driver as a module, choose M here: the module will - be called jtag. -+ -+menuconfig JTAG_ASPEED -+ tristate "Aspeed SoC JTAG controller support" -+ depends on JTAG && HAS_IOMEM -+ depends on ARCH_ASPEED || COMPILE_TEST -+ help -+ This provides a support for Aspeed JTAG device, equipped on -+ Aspeed SoC 24xx and 25xx families. Drivers allows programming -+ of hardware devices, connected to SoC through the JTAG interface. -+ -+ If you want this support, you should say Y here. -+ -+ To compile this driver as a module, choose M here: the module will -+ be called jtag-aspeed. -diff --git a/drivers/jtag/Makefile b/drivers/jtag/Makefile -index af37493..04a855e 100644 ---- a/drivers/jtag/Makefile -+++ b/drivers/jtag/Makefile -@@ -1 +1,2 @@ - obj-$(CONFIG_JTAG) += jtag.o -+obj-$(CONFIG_JTAG_ASPEED) += jtag-aspeed.o -diff --git a/drivers/jtag/jtag-aspeed.c b/drivers/jtag/jtag-aspeed.c -new file mode 100644 -index 0000000..1e6ace6 ---- /dev/null -+++ b/drivers/jtag/jtag-aspeed.c -@@ -0,0 +1,1524 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2018 Mellanox Technologies. All rights reserved. -+// Copyright (c) 2018 Oleksandr Shamray <oleksandrs@mellanox.com> -+// Copyright (c) 2019 Intel Corporation -+ -+#include <linux/clk.h> -+#include <linux/device.h> -+#include <linux/interrupt.h> -+#include <linux/jtag.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/of_address.h> -+#include <linux/platform_device.h> -+#include <linux/reset.h> -+#include <linux/slab.h> -+#include <linux/types.h> -+#include <linux/delay.h> -+#include <uapi/linux/jtag.h> -+ -+#define ASPEED_SCU_RESET_JTAG BIT(22) -+ -+#define ASPEED_JTAG_DATA 0x00 -+#define ASPEED_JTAG_INST 0x04 -+#define ASPEED_JTAG_CTRL 0x08 -+#define ASPEED_JTAG_ISR 0x0C -+#define ASPEED_JTAG_SW 0x10 -+#define ASPEED_JTAG_TCK 0x14 -+#define ASPEED_JTAG_EC 0x18 -+ -+#define ASPEED_JTAG_DATA_MSB 0x01 -+#define ASPEED_JTAG_DATA_CHUNK_SIZE 0x20 -+#define ASPEED_JTAG_HW2_DATA_CHUNK_SIZE 160 -+ -+/* ASPEED_JTAG_CTRL: Engine Control 24xx and 25xx series*/ -+#define ASPEED_JTAG_CTL_ENG_EN BIT(31) -+#define ASPEED_JTAG_CTL_ENG_OUT_EN BIT(30) -+#define ASPEED_JTAG_CTL_FORCE_TMS BIT(29) -+#define ASPEED_JTAG_CTL_IR_UPDATE BIT(26) -+#define ASPEED_JTAG_CTL_INST_LEN(x) ((x) << 20) -+#define ASPEED_JTAG_CTL_LASPEED_INST BIT(17) -+#define ASPEED_JTAG_CTL_INST_EN BIT(16) -+#define ASPEED_JTAG_CTL_DR_UPDATE BIT(10) -+#define ASPEED_JTAG_CTL_DATA_LEN(x) ((x) << 4) -+#define ASPEED_JTAG_CTL_LASPEED_DATA BIT(1) -+#define ASPEED_JTAG_CTL_DATA_EN BIT(0) -+ -+/* ASPEED_JTAG_CTRL: Engine Control 26xx series*/ -+#define ASPEED_JTAG_CTL_26XX_RESET_FIFO BIT(21) -+#define ASPEED_JTAG_CTL_26XX_FIFO_MODE_CTRL BIT(20) -+#define ASPEED_JTAG_CTL_26XX_TRANS_LEN(x) ((x) << 8) -+#define ASPEED_JTAG_CTL_26XX_TRANS_MASK GENMASK(17, 8) -+#define ASPEED_JTAG_CTL_26XX_MSB_FIRST BIT(6) -+#define ASPEED_JTAG_CTL_26XX_TERM_TRANS BIT(5) -+#define ASPEED_JTAG_CTL_26XX_LASPEED_TRANS BIT(4) -+#define ASPEED_JTAG_CTL_26XX_INST_EN BIT(1) -+ -+/* ASPEED_JTAG_ISR : Interrupt status and enable */ -+#define ASPEED_JTAG_ISR_INST_PAUSE BIT(19) -+#define ASPEED_JTAG_ISR_INST_COMPLETE BIT(18) -+#define ASPEED_JTAG_ISR_DATA_PAUSE BIT(17) -+#define ASPEED_JTAG_ISR_DATA_COMPLETE BIT(16) -+#define ASPEED_JTAG_ISR_INST_PAUSE_EN BIT(3) -+#define ASPEED_JTAG_ISR_INST_COMPLETE_EN BIT(2) -+#define ASPEED_JTAG_ISR_DATA_PAUSE_EN BIT(1) -+#define ASPEED_JTAG_ISR_DATA_COMPLETE_EN BIT(0) -+#define ASPEED_JTAG_ISR_INT_EN_MASK GENMASK(3, 0) -+#define ASPEED_JTAG_ISR_INT_MASK GENMASK(19, 16) -+ -+/* ASPEED_JTAG_SW : Software Mode and Status */ -+#define ASPEED_JTAG_SW_MODE_EN BIT(19) -+#define ASPEED_JTAG_SW_MODE_TCK BIT(18) -+#define ASPEED_JTAG_SW_MODE_TMS BIT(17) -+#define ASPEED_JTAG_SW_MODE_TDIO BIT(16) -+ -+/* ASPEED_JTAG_TCK : TCK Control */ -+#define ASPEED_JTAG_TCK_DIVISOR_MASK GENMASK(10, 0) -+#define ASPEED_JTAG_TCK_GET_DIV(x) ((x) & ASPEED_JTAG_TCK_DIVISOR_MASK) -+ -+/* ASPEED_JTAG_EC : Controller set for go to IDLE */ -+#define ASPEED_JTAG_EC_GO_IDLE BIT(0) -+ -+#define ASPEED_JTAG_IOUT_LEN(len) \ -+ (ASPEED_JTAG_CTL_ENG_EN | \ -+ ASPEED_JTAG_CTL_ENG_OUT_EN | \ -+ ASPEED_JTAG_CTL_INST_LEN(len)) -+ -+#define ASPEED_JTAG_DOUT_LEN(len) \ -+ (ASPEED_JTAG_CTL_ENG_EN | \ -+ ASPEED_JTAG_CTL_ENG_OUT_EN | \ -+ ASPEED_JTAG_CTL_DATA_LEN(len)) -+ -+#define ASPEED_JTAG_TRANS_LEN(len) \ -+ (ASPEED_JTAG_CTL_ENG_EN | \ -+ ASPEED_JTAG_CTL_ENG_OUT_EN | \ -+ ASPEED_JTAG_CTL_26XX_TRANS_LEN(len)) -+ -+#define ASPEED_JTAG_SW_TDIO (ASPEED_JTAG_SW_MODE_EN | ASPEED_JTAG_SW_MODE_TDIO) -+ -+#define ASPEED_JTAG_GET_TDI(direction, byte) \ -+ (((direction) & JTAG_WRITE_XFER) ? byte : UINT_MAX) -+ -+#define ASPEED_JTAG_TCK_WAIT 10 -+#define ASPEED_JTAG_RESET_CNTR 10 -+#define WAIT_ITERATIONS 75 -+ -+/* Use this macro to switch between HW mode 1(comment out) and 2(defined) */ -+#define ASPEED_JTAG_HW_MODE_2_ENABLE 1 -+ -+/* ASPEED JTAG HW MODE 2 (Only supported in AST26xx series) */ -+#define ASPEED_JTAG_SHDATA 0x20 -+#define ASPEED_JTAG_SHINST 0x24 -+#define ASPEED_JTAG_PADCTRL0 0x28 -+#define ASPEED_JTAG_PADCTRL1 0x2C -+#define ASPEED_JTAG_SHCTRL 0x30 -+#define ASPEED_JTAG_GBLCTRL 0x34 -+#define ASPEED_JTAG_INTCTRL 0x38 -+#define ASPEED_JTAG_STAT 0x3C -+ -+/* ASPEED_JTAG_PADCTRLx : Padding control 0 and 1 */ -+#define ASPEED_JTAG_PADCTRL_PAD_DATA BIT(24) -+#define ASPEED_JTAG_PADCTRL_POSTPAD(x) (((x) & GENMASK(8, 0)) << 12) -+#define ASPEED_JTAG_PADCTRL_PREPAD(x) (((x) & GENMASK(8, 0)) << 0) -+ -+/* ASPEED_JTAG_SHCTRL: Shift Control */ -+#define ASPEED_JTAG_SHCTRL_FRUN_TCK_EN BIT(31) -+#define ASPEED_JTAG_SHCTRL_STSHIFT_EN BIT(30) -+#define ASPEED_JTAG_SHCTRL_TMS(x) (((x) & GENMASK(13, 0)) << 16) -+#define ASPEED_JTAG_SHCTRL_POST_TMS(x) (((x) & GENMASK(3, 0)) << 13) -+#define ASPEED_JTAG_SHCTRL_PRE_TMS(x) (((x) & GENMASK(3, 0)) << 10) -+#define ASPEED_JTAG_SHCTRL_PAD_SEL0 (0) -+#define ASPEED_JTAG_SHCTRL_PAD_SEL1 BIT(9) -+#define ASPEED_JTAG_SHCTRL_END_SHIFT BIT(8) -+#define ASPEED_JTAG_SHCTRL_START_SHIFT BIT(7) -+#define ASPEED_JTAG_SHCTRL_LWRDT_SHIFT(x) ((x) & GENMASK(6, 0)) -+ -+#define ASPEED_JTAG_END_SHIFT_DISABLED 0 -+ -+/* ASPEED_JTAG_GBLCTRL : Global Control */ -+#define ASPEED_JTAG_GBLCTRL_ENG_MODE_EN BIT(31) -+#define ASPEED_JTAG_GBLCTRL_ENG_OUT_EN BIT(30) -+#define ASPEED_JTAG_GBLCTRL_FORCE_TMS BIT(29) -+#define ASPEED_JTAG_GBLCTRL_SHIFT_COMPLETE BIT(28) -+#define ASPEED_JTAG_GBLCTRL_RESET_FIFO BIT(25) -+#define ASPEED_JTAG_GBLCTRL_FIFO_CTRL_MODE BIT(24) -+#define ASPEED_JTAG_GBLCTRL_UPDT_SHIFT(x) (((x) & GENMASK(9, 7)) << 13) -+#define ASPEED_JTAG_GBLCTRL_STSHIFT(x) (((x) & GENMASK(0, 0)) << 16) -+#define ASPEED_JTAG_GBLCTRL_TRST BIT(15) -+#define ASPEED_JTAG_CLK_DIVISOR_MASK GENMASK(11, 0) -+#define ASPEED_JTAG_CLK_GET_DIV(x) ((x) & ASPEED_JTAG_CLK_DIVISOR_MASK) -+ -+/* ASPEED_JTAG_INTCTRL: Interrupt Control */ -+#define ASPEED_JTAG_INTCTRL_SHCPL_IRQ_EN BIT(16) -+#define ASPEED_JTAG_INTCTRL_SHCPL_IRQ_STAT BIT(0) -+ -+/* ASPEED_JTAG_STAT: JTAG HW mode 2 status */ -+#define ASPEED_JTAG_STAT_ENG_IDLE BIT(0) -+ -+/*#define USE_INTERRUPTS*/ -+#define DEBUG_JTAG -+ -+static const char * const regnames[] = { -+ [ASPEED_JTAG_DATA] = "ASPEED_JTAG_DATA", -+ [ASPEED_JTAG_INST] = "ASPEED_JTAG_INST", -+ [ASPEED_JTAG_CTRL] = "ASPEED_JTAG_CTRL", -+ [ASPEED_JTAG_ISR] = "ASPEED_JTAG_ISR", -+ [ASPEED_JTAG_SW] = "ASPEED_JTAG_SW", -+ [ASPEED_JTAG_TCK] = "ASPEED_JTAG_TCK", -+ [ASPEED_JTAG_EC] = "ASPEED_JTAG_EC", -+ [ASPEED_JTAG_SHDATA] = "ASPEED_JTAG_SHDATA", -+ [ASPEED_JTAG_SHINST] = "ASPEED_JTAG_SHINST", -+ [ASPEED_JTAG_PADCTRL0] = "ASPEED_JTAG_PADCTRL0", -+ [ASPEED_JTAG_PADCTRL1] = "ASPEED_JTAG_PADCTRL1", -+ [ASPEED_JTAG_SHCTRL] = "ASPEED_JTAG_SHCTRL", -+ [ASPEED_JTAG_GBLCTRL] = "ASPEED_JTAG_GBLCTRL", -+ [ASPEED_JTAG_INTCTRL] = "ASPEED_JTAG_INTCTRL", -+ [ASPEED_JTAG_STAT] = "ASPEED_JTAG_STAT", -+}; -+ -+#define ASPEED_JTAG_NAME "jtag-aspeed" -+ -+struct aspeed_jtag { -+ void __iomem *reg_base; -+ struct device *dev; -+ struct clk *pclk; -+ enum jtag_tapstate status; -+ int irq; -+ struct reset_control *rst; -+ u32 flag; -+ wait_queue_head_t jtag_wq; -+ u32 mode; -+ const struct jtag_low_level_functions *llops; -+}; -+ -+/* Multi generation support is enabled by fops and low level assped function -+ * mapping using asped_jtag_functions struct as config mechanism. -+ */ -+ -+struct jtag_low_level_functions { -+ void (*output_disable)(struct aspeed_jtag *aspeed_jtag); -+ void (*master_enable)(struct aspeed_jtag *aspeed_jtag); -+ int (*xfer_push_data)(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_xfer_type type, u32 bits_len); -+ int (*xfer_push_data_last)(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_xfer_type type, u32 bits_len); -+ void (*xfer_sw)(struct aspeed_jtag *aspeed_jtag, struct jtag_xfer *xfer, -+ u32 *data); -+ int (*xfer_hw)(struct aspeed_jtag *aspeed_jtag, struct jtag_xfer *xfer, -+ u32 *data); -+}; -+ -+struct aspeed_jtag_functions { -+ const struct jtag_ops *aspeed_jtag_ops; -+ const struct jtag_low_level_functions *aspeed_jtag_llops; -+}; -+ -+/* -+ * This structure represents a TMS cycle, as expressed in a set of bits and a -+ * count of bits (note: there are no start->end state transitions that require -+ * more than 1 byte of TMS cycles) -+ */ -+struct tms_cycle { -+ unsigned char tmsbits; -+ unsigned char count; -+}; -+ -+/* -+ * This is the complete set TMS cycles for going from any TAP state to any -+ * other TAP state, following a "shortest path" rule. -+ */ -+static const struct tms_cycle _tms_cycle_lookup[][16] = { -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* TLR */{{0x00, 0}, {0x00, 1}, {0x02, 2}, {0x02, 3}, {0x02, 4}, {0x0a, 4}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x0a, 5}, {0x2a, 6}, {0x1a, 5}, {0x06, 3}, {0x06, 4}, {0x06, 5}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x16, 5}, {0x16, 6}, {0x56, 7}, {0x36, 6} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* RTI */{{0x07, 3}, {0x00, 0}, {0x01, 1}, {0x01, 2}, {0x01, 3}, {0x05, 3}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x05, 4}, {0x15, 5}, {0x0d, 4}, {0x03, 2}, {0x03, 3}, {0x03, 4}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x0b, 4}, {0x0b, 5}, {0x2b, 6}, {0x1b, 5} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* SelDR*/{{0x03, 2}, {0x03, 3}, {0x00, 0}, {0x00, 1}, {0x00, 2}, {0x02, 2}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x02, 3}, {0x0a, 4}, {0x06, 3}, {0x01, 1}, {0x01, 2}, {0x01, 3}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x05, 3}, {0x05, 4}, {0x15, 5}, {0x0d, 4} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* CapDR*/{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x00, 0}, {0x00, 1}, {0x01, 1}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x01, 2}, {0x05, 3}, {0x03, 2}, {0x0f, 4}, {0x0f, 5}, {0x0f, 6}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x2f, 6}, {0x2f, 7}, {0xaf, 8}, {0x6f, 7} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* SDR */{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x00, 0}, {0x01, 1}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x01, 2}, {0x05, 3}, {0x03, 2}, {0x0f, 4}, {0x0f, 5}, {0x0f, 6}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x2f, 6}, {0x2f, 7}, {0xaf, 8}, {0x6f, 7} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* Ex1DR*/{{0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x02, 3}, {0x00, 0}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x00, 1}, {0x02, 2}, {0x01, 1}, {0x07, 3}, {0x07, 4}, {0x07, 5}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x17, 5}, {0x17, 6}, {0x57, 7}, {0x37, 6} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* PDR */{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x01, 2}, {0x05, 3}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x00, 0}, {0x01, 1}, {0x03, 2}, {0x0f, 4}, {0x0f, 5}, {0x0f, 6}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x2f, 6}, {0x2f, 7}, {0xaf, 8}, {0x6f, 7} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* Ex2DR*/{{0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x00, 1}, {0x02, 2}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x02, 3}, {0x00, 0}, {0x01, 1}, {0x07, 3}, {0x07, 4}, {0x07, 5}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x17, 5}, {0x17, 6}, {0x57, 7}, {0x37, 6} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* UpdDR*/{{0x07, 3}, {0x00, 1}, {0x01, 1}, {0x01, 2}, {0x01, 3}, {0x05, 3}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x05, 4}, {0x15, 5}, {0x00, 0}, {0x03, 2}, {0x03, 3}, {0x03, 4}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x0b, 4}, {0x0b, 5}, {0x2b, 6}, {0x1b, 5} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* SelIR*/{{0x01, 1}, {0x01, 2}, {0x05, 3}, {0x05, 4}, {0x05, 5}, {0x15, 5}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x15, 6}, {0x55, 7}, {0x35, 6}, {0x00, 0}, {0x00, 1}, {0x00, 2}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x02, 2}, {0x02, 3}, {0x0a, 4}, {0x06, 3} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* CapIR*/{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x07, 5}, {0x17, 5}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x17, 6}, {0x57, 7}, {0x37, 6}, {0x0f, 4}, {0x00, 0}, {0x00, 1}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x01, 1}, {0x01, 2}, {0x05, 3}, {0x03, 2} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* SIR */{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x07, 5}, {0x17, 5}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x17, 6}, {0x57, 7}, {0x37, 6}, {0x0f, 4}, {0x0f, 5}, {0x00, 0}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x01, 1}, {0x01, 2}, {0x05, 3}, {0x03, 2} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* Ex1IR*/{{0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x03, 4}, {0x0b, 4}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x0b, 5}, {0x2b, 6}, {0x1b, 5}, {0x07, 3}, {0x07, 4}, {0x02, 3}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x00, 0}, {0x00, 1}, {0x02, 2}, {0x01, 1} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* PIR */{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x07, 5}, {0x17, 5}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x17, 6}, {0x57, 7}, {0x37, 6}, {0x0f, 4}, {0x0f, 5}, {0x01, 2}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x05, 3}, {0x00, 0}, {0x01, 1}, {0x03, 2} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* Ex2IR*/{{0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x03, 4}, {0x0b, 4}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x0b, 5}, {0x2b, 6}, {0x1b, 5}, {0x07, 3}, {0x07, 4}, {0x00, 1}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x02, 2}, {0x02, 3}, {0x00, 0}, {0x01, 1} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* UpdIR*/{{0x07, 3}, {0x00, 1}, {0x01, 1}, {0x01, 2}, {0x01, 3}, {0x05, 3}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x05, 4}, {0x15, 5}, {0x0d, 4}, {0x03, 2}, {0x03, 3}, {0x03, 4}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x0b, 4}, {0x0b, 5}, {0x2b, 6}, {0x00, 0} }, -+}; -+ -+#ifdef DEBUG_JTAG -+static char *end_status_str[] = { "tlr", "idle", "selDR", "capDR", -+ "sDR", "ex1DR", "pDR", "ex2DR", -+ "updDR", "selIR", "capIR", "sIR", -+ "ex1IR", "pIR", "ex2IR", "updIR" }; -+#endif -+ -+static u32 aspeed_jtag_read(struct aspeed_jtag *aspeed_jtag, u32 reg) -+{ -+ u32 val = readl(aspeed_jtag->reg_base + reg); -+ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "read:%s val = 0x%08x\n", regnames[reg], val); -+#endif -+ return val; -+} -+ -+static void aspeed_jtag_write(struct aspeed_jtag *aspeed_jtag, u32 val, u32 reg) -+{ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "write:%s val = 0x%08x\n", regnames[reg], -+ val); -+#endif -+ writel(val, aspeed_jtag->reg_base + reg); -+} -+ -+static int aspeed_jtag_freq_set(struct jtag *jtag, u32 freq) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ unsigned long apb_frq; -+ u32 tck_val; -+ u16 div; -+ -+ if (!freq) -+ return -EINVAL; -+ -+ apb_frq = clk_get_rate(aspeed_jtag->pclk); -+ if (!apb_frq) -+ return -ENOTSUPP; -+ -+ div = (apb_frq - 1) / freq; -+ tck_val = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_TCK); -+ aspeed_jtag_write(aspeed_jtag, -+ (tck_val & ~ASPEED_JTAG_TCK_DIVISOR_MASK) | div, -+ ASPEED_JTAG_TCK); -+ return 0; -+} -+ -+static int aspeed_jtag_freq_set_26xx(struct jtag *jtag, u32 freq) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ unsigned long apb_frq; -+ u32 tck_val; -+ u16 div; -+ -+ if (!freq) -+ return -EINVAL; -+ -+ apb_frq = clk_get_rate(aspeed_jtag->pclk); -+ if (!apb_frq) -+ return -ENOTSUPP; -+ -+ div = (apb_frq - 1) / freq; -+ tck_val = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_GBLCTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ (tck_val & ~ASPEED_JTAG_CLK_DIVISOR_MASK) | div, -+ ASPEED_JTAG_GBLCTRL); -+ return 0; -+} -+ -+static int aspeed_jtag_freq_get(struct jtag *jtag, u32 *frq) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ u32 pclk; -+ u32 tck; -+ -+ pclk = clk_get_rate(aspeed_jtag->pclk); -+ tck = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_TCK); -+ *frq = pclk / (ASPEED_JTAG_TCK_GET_DIV(tck) + 1); -+ -+ return 0; -+} -+ -+static int aspeed_jtag_freq_get_26xx(struct jtag *jtag, u32 *frq) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ u32 pclk; -+ u32 tck; -+ -+ pclk = clk_get_rate(aspeed_jtag->pclk); -+ tck = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_GBLCTRL); -+ *frq = pclk / (ASPEED_JTAG_CLK_GET_DIV(tck) + 1); -+ -+ return 0; -+} -+ -+static inline void aspeed_jtag_output_disable(struct aspeed_jtag *aspeed_jtag) -+{ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_CTRL); -+} -+ -+static inline void -+aspeed_jtag_output_disable_26xx(struct aspeed_jtag *aspeed_jtag) -+{ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_GBLCTRL); -+} -+ -+static inline void aspeed_jtag_master(struct aspeed_jtag *aspeed_jtag) -+{ -+ aspeed_jtag_write(aspeed_jtag, -+ (ASPEED_JTAG_CTL_ENG_EN | ASPEED_JTAG_CTL_ENG_OUT_EN), -+ ASPEED_JTAG_CTRL); -+ -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_SW_MODE_EN | ASPEED_JTAG_SW_MODE_TDIO, -+ ASPEED_JTAG_SW); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_ISR_INST_PAUSE | -+ ASPEED_JTAG_ISR_INST_COMPLETE | -+ ASPEED_JTAG_ISR_DATA_PAUSE | -+ ASPEED_JTAG_ISR_DATA_COMPLETE | -+ ASPEED_JTAG_ISR_INST_PAUSE_EN | -+ ASPEED_JTAG_ISR_INST_COMPLETE_EN | -+ ASPEED_JTAG_ISR_DATA_PAUSE_EN | -+ ASPEED_JTAG_ISR_DATA_COMPLETE_EN, -+ ASPEED_JTAG_ISR); /* Enable Interrupt */ -+} -+ -+static inline void aspeed_jtag_master_26xx(struct aspeed_jtag *aspeed_jtag) -+{ -+ if (aspeed_jtag->mode & JTAG_XFER_HW_MODE) { -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_CTRL); -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_SW); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_GBLCTRL_ENG_MODE_EN | -+ ASPEED_JTAG_GBLCTRL_ENG_OUT_EN, -+ ASPEED_JTAG_GBLCTRL); -+ -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_INTCTRL_SHCPL_IRQ_EN | -+ ASPEED_JTAG_INTCTRL_SHCPL_IRQ_STAT, -+ ASPEED_JTAG_INTCTRL); /* Enable Interrupt */ -+ } else { -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_GBLCTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_CTL_ENG_EN | -+ ASPEED_JTAG_CTL_ENG_OUT_EN, -+ ASPEED_JTAG_CTRL); -+ -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_SW_MODE_EN | -+ ASPEED_JTAG_SW_MODE_TDIO, -+ ASPEED_JTAG_SW); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_ISR_INST_PAUSE | -+ ASPEED_JTAG_ISR_INST_COMPLETE | -+ ASPEED_JTAG_ISR_DATA_PAUSE | -+ ASPEED_JTAG_ISR_DATA_COMPLETE | -+ ASPEED_JTAG_ISR_INST_PAUSE_EN | -+ ASPEED_JTAG_ISR_INST_COMPLETE_EN | -+ ASPEED_JTAG_ISR_DATA_PAUSE_EN | -+ ASPEED_JTAG_ISR_DATA_COMPLETE_EN, -+ ASPEED_JTAG_ISR); /* Enable Interrupt */ -+ } -+} -+ -+static int aspeed_jtag_mode_set(struct jtag *jtag, struct jtag_mode *jtag_mode) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+ switch (jtag_mode->feature) { -+ case JTAG_XFER_MODE: -+ aspeed_jtag->mode = jtag_mode->mode; -+ aspeed_jtag->llops->master_enable(aspeed_jtag); -+ break; -+ case JTAG_CONTROL_MODE: -+ if (jtag_mode->mode == JTAG_MASTER_OUTPUT_DISABLE) -+ aspeed_jtag->llops->output_disable(aspeed_jtag); -+ else if (jtag_mode->mode == JTAG_MASTER_MODE) -+ aspeed_jtag->llops->master_enable(aspeed_jtag); -+ break; -+ default: -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+static char aspeed_jtag_tck_cycle(struct aspeed_jtag *aspeed_jtag, u8 tms, -+ u8 tdi) -+{ -+ char tdo = 0; -+ -+ /* TCK = 0 */ -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_SW_MODE_EN | -+ (tms * ASPEED_JTAG_SW_MODE_TMS) | -+ (tdi * ASPEED_JTAG_SW_MODE_TDIO), -+ ASPEED_JTAG_SW); -+ -+ aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_SW); -+ -+ /* TCK = 1 */ -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_SW_MODE_EN | ASPEED_JTAG_SW_MODE_TCK | -+ (tms * ASPEED_JTAG_SW_MODE_TMS) | -+ (tdi * ASPEED_JTAG_SW_MODE_TDIO), -+ ASPEED_JTAG_SW); -+ -+ if (aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_SW) & -+ ASPEED_JTAG_SW_MODE_TDIO) -+ tdo = 1; -+ -+ return tdo; -+} -+ -+static int aspeed_jtag_bitbang(struct jtag *jtag, -+ struct bitbang_packet *bitbang, -+ struct tck_bitbang *bitbang_data) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ int i = 0; -+ -+ for (i = 0; i < bitbang->length; i++) { -+ bitbang_data[i].tdo = -+ aspeed_jtag_tck_cycle(aspeed_jtag, bitbang_data[i].tms, -+ bitbang_data[i].tdi); -+ } -+ return 0; -+} -+ -+static int aspeed_jtag_isr_wait(struct aspeed_jtag *aspeed_jtag, u32 bit) -+{ -+ int res = 0; -+#ifdef USE_INTERRUPTS -+ res = wait_event_interruptible(aspeed_jtag->jtag_wq, -+ aspeed_jtag->flag & bit); -+ aspeed_jtag->flag &= ~bit; -+#else -+ u32 status = 0; -+ u32 iterations = 0; -+ -+ while ((status & bit) == 0) { -+ status = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_ISR); -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "%s = 0x%08x\n", __func__, status); -+#endif -+ iterations++; -+ if (iterations > WAIT_ITERATIONS) { -+ dev_err(aspeed_jtag->dev, "%s %d in ASPEED_JTAG_ISR\n", -+ "aspeed_jtag driver timed out waiting for bit", -+ bit); -+ res = -EFAULT; -+ break; -+ } -+ if ((status & ASPEED_JTAG_ISR_DATA_COMPLETE) == 0) { -+ if (iterations % 25 == 0) -+ usleep_range(1, 5); -+ else -+ udelay(1); -+ } -+ } -+ aspeed_jtag_write(aspeed_jtag, bit | (status & 0xf), ASPEED_JTAG_ISR); -+#endif -+ return res; -+} -+ -+static int aspeed_jtag_wait_shift_complete(struct aspeed_jtag *aspeed_jtag) -+{ -+ int res = 0; -+#ifdef USE_INTERRUPTS -+ res = wait_event_interruptible(aspeed_jtag->jtag_wq, -+ aspeed_jtag->flag & -+ ASPEED_JTAG_INTCTRL_SHCPL_IRQ_STAT); -+ aspeed_jtag->flag &= ~ASPEED_JTAG_INTCTRL_SHCPL_IRQ_STAT; -+#else -+ u32 status = 0; -+ u32 iterations = 0; -+ -+ while ((status & ASPEED_JTAG_INTCTRL_SHCPL_IRQ_STAT) == 0) { -+ status = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_INTCTRL); -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "%s = 0x%08x\n", __func__, status); -+#endif -+ iterations++; -+ if (iterations > WAIT_ITERATIONS) { -+ dev_err(aspeed_jtag->dev, -+ "aspeed_jtag driver timed out waiting for shift completed\n"); -+ res = -EFAULT; -+ break; -+ } -+ if (iterations % 25 == 0) -+ usleep_range(1, 5); -+ else -+ udelay(1); -+ } -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_INTCTRL_SHCPL_IRQ_STAT | -+ ASPEED_JTAG_INTCTRL_SHCPL_IRQ_EN, -+ ASPEED_JTAG_INTCTRL); -+#endif -+ return res; -+} -+ -+static void aspeed_jtag_set_tap_state(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_tapstate from_state, -+ enum jtag_tapstate end_state) -+{ -+ int i = 0; -+ enum jtag_tapstate from, to; -+ -+ from = from_state; -+ to = end_state; -+ -+ if (from == JTAG_STATE_CURRENT) -+ from = aspeed_jtag->status; -+ -+ for (i = 0; i < _tms_cycle_lookup[from][to].count; i++) -+ aspeed_jtag_tck_cycle(aspeed_jtag, -+ ((_tms_cycle_lookup[from][to].tmsbits -+ >> i) & 0x1), 0); -+ aspeed_jtag->status = end_state; -+} -+ -+static void aspeed_jtag_set_tap_state_sw(struct aspeed_jtag *aspeed_jtag, -+ struct jtag_tap_state *tapstate) -+{ -+ /* SW mode from curent tap state -> to end_state */ -+ if (tapstate->reset) { -+ int i = 0; -+ -+ for (i = 0; i < ASPEED_JTAG_RESET_CNTR; i++) -+ aspeed_jtag_tck_cycle(aspeed_jtag, 1, 0); -+ aspeed_jtag->status = JTAG_STATE_TLRESET; -+ } -+ -+ aspeed_jtag_set_tap_state(aspeed_jtag, tapstate->from, -+ tapstate->endstate); -+} -+ -+static int aspeed_jtag_status_set(struct jtag *jtag, -+ struct jtag_tap_state *tapstate) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "Set TAP state: %s\n", -+ end_status_str[tapstate->endstate]); -+#endif -+ -+ if (!(aspeed_jtag->mode & JTAG_XFER_HW_MODE)) { -+ aspeed_jtag_set_tap_state_sw(aspeed_jtag, tapstate); -+ return 0; -+ } -+ -+ /* x TMS high + 1 TMS low */ -+ if (tapstate->reset) { -+ /* Disable sw mode */ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_SW); -+ mdelay(1); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_CTL_ENG_EN | -+ ASPEED_JTAG_CTL_ENG_OUT_EN | -+ ASPEED_JTAG_CTL_FORCE_TMS, -+ ASPEED_JTAG_CTRL); -+ mdelay(1); -+ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_TDIO, -+ ASPEED_JTAG_SW); -+ aspeed_jtag->status = JTAG_STATE_TLRESET; -+ } -+ -+ return 0; -+} -+ -+static void aspeed_jtag_shctrl_tms_mask(enum jtag_tapstate from, -+ enum jtag_tapstate to, -+ enum jtag_tapstate there, -+ enum jtag_tapstate endstate, -+ u32 start_shift, u32 end_shift, -+ u32 *tms_mask) -+{ -+ u32 pre_tms = start_shift ? _tms_cycle_lookup[from][to].count : 0; -+ u32 post_tms = end_shift ? _tms_cycle_lookup[there][endstate].count : 0; -+ u32 tms_value = start_shift ? _tms_cycle_lookup[from][to].tmsbits : 0; -+ -+ tms_value |= end_shift ? _tms_cycle_lookup[there][endstate].tmsbits -+ << pre_tms : -+ 0; -+ *tms_mask = start_shift | ASPEED_JTAG_SHCTRL_PRE_TMS(pre_tms) | -+ end_shift | ASPEED_JTAG_SHCTRL_POST_TMS(post_tms) | -+ ASPEED_JTAG_SHCTRL_TMS(tms_value); -+} -+ -+static void aspeed_jtag_set_tap_state_hw2(struct aspeed_jtag *aspeed_jtag, -+ struct jtag_tap_state *tapstate) -+{ -+ u32 reg_val; -+ u32 start_shift = ASPEED_JTAG_SHCTRL_START_SHIFT; -+ u32 tms_mask = 0; -+ -+ /* x TMS high + 1 TMS low */ -+ if (tapstate->reset) { -+ /* Disable sw mode */ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_SW); -+ mdelay(1); -+ reg_val = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_GBLCTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ reg_val | ASPEED_JTAG_GBLCTRL_ENG_MODE_EN | -+ ASPEED_JTAG_GBLCTRL_ENG_OUT_EN | -+ ASPEED_JTAG_GBLCTRL_RESET_FIFO | -+ ASPEED_JTAG_GBLCTRL_FORCE_TMS, -+ ASPEED_JTAG_GBLCTRL); -+ mdelay(1); -+ aspeed_jtag->status = JTAG_STATE_TLRESET; -+ return; -+ } -+ -+ if (tapstate->from != tapstate->endstate) { -+ aspeed_jtag_shctrl_tms_mask(tapstate->from, tapstate->endstate, -+ JTAG_STATE_TLRESET, -+ JTAG_STATE_TLRESET, start_shift, -+ ASPEED_JTAG_END_SHIFT_DISABLED, -+ &tms_mask); -+ -+ /* Trigger a 0 bit transfer to execute pre tms flow*/ -+ aspeed_jtag_write(aspeed_jtag, -+ tms_mask | ASPEED_JTAG_SHCTRL_LWRDT_SHIFT(0), -+ ASPEED_JTAG_SHCTRL); -+ aspeed_jtag_wait_shift_complete(aspeed_jtag); -+ reg_val = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_GBLCTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ reg_val | ASPEED_JTAG_GBLCTRL_RESET_FIFO, -+ ASPEED_JTAG_GBLCTRL); -+ } -+ aspeed_jtag->status = tapstate->endstate; -+} -+ -+static int aspeed_jtag_status_set_26xx(struct jtag *jtag, -+ struct jtag_tap_state *tapstate) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "Set TAP state: %s\n", -+ end_status_str[tapstate->endstate]); -+#endif -+ -+ if (!(aspeed_jtag->mode & JTAG_XFER_HW_MODE)) { -+ aspeed_jtag_set_tap_state_sw(aspeed_jtag, tapstate); -+ return 0; -+ } -+ -+ aspeed_jtag_set_tap_state_hw2(aspeed_jtag, tapstate); -+ return 0; -+} -+ -+static void aspeed_jtag_xfer_sw(struct aspeed_jtag *aspeed_jtag, -+ struct jtag_xfer *xfer, u32 *data) -+{ -+ unsigned long remain_xfer = xfer->length; -+ unsigned long shift_bits = 0; -+ unsigned long index = 0; -+ unsigned long tdi; -+ char tdo; -+ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "SW JTAG SHIFT %s, length = %d\n", -+ (xfer->type == JTAG_SIR_XFER) ? "IR" : "DR", xfer->length); -+#endif -+ -+ if (xfer->type == JTAG_SIR_XFER) -+ aspeed_jtag_set_tap_state(aspeed_jtag, xfer->from, -+ JTAG_STATE_SHIFTIR); -+ else -+ aspeed_jtag_set_tap_state(aspeed_jtag, xfer->from, -+ JTAG_STATE_SHIFTDR); -+ -+ tdi = ASPEED_JTAG_GET_TDI(xfer->direction, data[index]); -+ data[index] = 0; -+ while (remain_xfer > 1) { -+ tdo = aspeed_jtag_tck_cycle(aspeed_jtag, 0, -+ tdi & ASPEED_JTAG_DATA_MSB); -+ data[index] |= tdo -+ << (shift_bits % ASPEED_JTAG_DATA_CHUNK_SIZE); -+ tdi >>= 1; -+ shift_bits++; -+ remain_xfer--; -+ -+ if (shift_bits % ASPEED_JTAG_DATA_CHUNK_SIZE == 0) { -+ tdo = 0; -+ index++; -+ tdi = ASPEED_JTAG_GET_TDI(xfer->direction, data[index]); -+ data[index] = 0; -+ } -+ } -+ -+ if ((xfer->endstate == (xfer->type == JTAG_SIR_XFER ? -+ JTAG_STATE_SHIFTIR : -+ JTAG_STATE_SHIFTDR))) { -+ /* Stay in Shift IR/DR*/ -+ tdo = aspeed_jtag_tck_cycle(aspeed_jtag, 0, -+ tdi & ASPEED_JTAG_DATA_MSB); -+ data[index] |= tdo -+ << (shift_bits % ASPEED_JTAG_DATA_CHUNK_SIZE); -+ } else { -+ /* Goto end state */ -+ tdo = aspeed_jtag_tck_cycle(aspeed_jtag, 1, -+ tdi & ASPEED_JTAG_DATA_MSB); -+ data[index] |= tdo -+ << (shift_bits % ASPEED_JTAG_DATA_CHUNK_SIZE); -+ aspeed_jtag->status = (xfer->type == JTAG_SIR_XFER) ? -+ JTAG_STATE_EXIT1IR : -+ JTAG_STATE_EXIT1DR; -+ aspeed_jtag_set_tap_state(aspeed_jtag, aspeed_jtag->status, -+ xfer->endstate); -+ } -+} -+ -+static int aspeed_jtag_xfer_push_data_26xx(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_xfer_type type, -+ u32 bits_len) -+{ -+ int res = 0; -+ -+ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_TRANS_LEN(bits_len), -+ ASPEED_JTAG_CTRL); -+ if (type == JTAG_SIR_XFER) { -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_TRANS_LEN(bits_len) | -+ ASPEED_JTAG_CTL_26XX_INST_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_INST_PAUSE); -+ } else { -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_TRANS_LEN(bits_len) | -+ ASPEED_JTAG_CTL_DATA_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_DATA_PAUSE); -+ } -+ return res; -+} -+ -+static int aspeed_jtag_xfer_push_data(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_xfer_type type, u32 bits_len) -+{ -+ int res = 0; -+ -+ if (type == JTAG_SIR_XFER) { -+ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_IOUT_LEN(bits_len), -+ ASPEED_JTAG_CTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_IOUT_LEN(bits_len) | -+ ASPEED_JTAG_CTL_INST_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_INST_PAUSE); -+ } else { -+ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_DOUT_LEN(bits_len), -+ ASPEED_JTAG_CTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_DOUT_LEN(bits_len) | -+ ASPEED_JTAG_CTL_DATA_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_DATA_PAUSE); -+ } -+ return res; -+} -+ -+static int aspeed_jtag_xfer_push_data_last_26xx(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_xfer_type type, -+ u32 shift_bits) -+{ -+ int res = 0; -+ -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_TRANS_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_26XX_LASPEED_TRANS, -+ ASPEED_JTAG_CTRL); -+ if (type == JTAG_SIR_XFER) { -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_TRANS_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_26XX_LASPEED_TRANS | -+ ASPEED_JTAG_CTL_26XX_INST_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_INST_COMPLETE); -+ } else { -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_TRANS_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_26XX_LASPEED_TRANS | -+ ASPEED_JTAG_CTL_DATA_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_DATA_COMPLETE); -+ } -+ return res; -+} -+ -+static int aspeed_jtag_xfer_push_data_last(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_xfer_type type, -+ u32 shift_bits) -+{ -+ int res = 0; -+ -+ if (type == JTAG_SIR_XFER) { -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_IOUT_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_LASPEED_INST, -+ ASPEED_JTAG_CTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_IOUT_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_LASPEED_INST | -+ ASPEED_JTAG_CTL_INST_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_INST_COMPLETE); -+ } else { -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_DOUT_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_LASPEED_DATA, -+ ASPEED_JTAG_CTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_DOUT_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_LASPEED_DATA | -+ ASPEED_JTAG_CTL_DATA_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_DATA_COMPLETE); -+ } -+ return res; -+} -+ -+static int aspeed_jtag_xfer_hw(struct aspeed_jtag *aspeed_jtag, -+ struct jtag_xfer *xfer, u32 *data) -+{ -+ unsigned long remain_xfer = xfer->length; -+ unsigned long index = 0; -+ char shift_bits; -+ u32 data_reg; -+ u32 scan_end; -+ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "HW JTAG SHIFT %s, length = %d\n", -+ (xfer->type == JTAG_SIR_XFER) ? "IR" : "DR", xfer->length); -+#endif -+ data_reg = xfer->type == JTAG_SIR_XFER ? ASPEED_JTAG_INST : -+ ASPEED_JTAG_DATA; -+ if (xfer->endstate == JTAG_STATE_SHIFTIR || -+ xfer->endstate == JTAG_STATE_SHIFTDR || -+ xfer->endstate == JTAG_STATE_PAUSEIR || -+ xfer->endstate == JTAG_STATE_PAUSEDR) { -+ scan_end = 0; -+ } else { -+ scan_end = 1; -+ } -+ -+ while (remain_xfer) { -+ if (xfer->direction & JTAG_WRITE_XFER) -+ aspeed_jtag_write(aspeed_jtag, data[index], data_reg); -+ else -+ aspeed_jtag_write(aspeed_jtag, 0, data_reg); -+ -+ if (remain_xfer > ASPEED_JTAG_DATA_CHUNK_SIZE) { -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, -+ "Chunk len=%d chunk_size=%d remain_xfer=%lu\n", -+ xfer->length, ASPEED_JTAG_DATA_CHUNK_SIZE, -+ remain_xfer); -+#endif -+ shift_bits = ASPEED_JTAG_DATA_CHUNK_SIZE; -+ -+ /* -+ * Transmit bytes that were not equals to column length -+ * and after the transfer go to Pause IR/DR. -+ */ -+ if (aspeed_jtag->llops->xfer_push_data(aspeed_jtag, -+ xfer->type, -+ shift_bits) -+ != 0) { -+ return -EFAULT; -+ } -+ } else { -+ /* -+ * Read bytes equals to column length -+ */ -+ shift_bits = remain_xfer; -+ if (scan_end) { -+ /* -+ * If this data is the end of the transmission -+ * send remaining bits and go to endstate -+ */ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, -+ "Last len=%d chunk_size=%d remain_xfer=%lu\n", -+ xfer->length, -+ ASPEED_JTAG_DATA_CHUNK_SIZE, -+ remain_xfer); -+#endif -+ if (aspeed_jtag->llops->xfer_push_data_last( -+ aspeed_jtag, xfer->type, -+ shift_bits) != 0) { -+ return -EFAULT; -+ } -+ } else { -+ /* -+ * If transmission is waiting for additional -+ * data send remaining bits and then go to -+ * Pause IR/DR. -+ */ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, -+ "Tail len=%d chunk_size=%d remain_xfer=%lu\n", -+ xfer->length, -+ ASPEED_JTAG_DATA_CHUNK_SIZE, -+ remain_xfer); -+#endif -+ if (aspeed_jtag->llops->xfer_push_data( -+ aspeed_jtag, xfer->type, -+ shift_bits) != 0) { -+ return -EFAULT; -+ } -+ } -+ } -+ -+ if (xfer->direction & JTAG_READ_XFER) { -+ if (shift_bits < ASPEED_JTAG_DATA_CHUNK_SIZE) { -+ data[index] = -+ aspeed_jtag_read(aspeed_jtag, data_reg); -+ -+ data[index] >>= ASPEED_JTAG_DATA_CHUNK_SIZE - -+ shift_bits; -+ } else { -+ data[index] = -+ aspeed_jtag_read(aspeed_jtag, data_reg); -+ } -+ } -+ -+ remain_xfer = remain_xfer - shift_bits; -+ index++; -+ } -+ return 0; -+} -+ -+static int aspeed_jtag_xfer(struct jtag *jtag, struct jtag_xfer *xfer, -+ u8 *xfer_data) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+ if (!(aspeed_jtag->mode & JTAG_XFER_HW_MODE)) { -+ /* SW mode */ -+ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_TDIO, -+ ASPEED_JTAG_SW); -+ -+ aspeed_jtag->llops->xfer_sw(aspeed_jtag, xfer, -+ (u32 *)xfer_data); -+ } else { -+ /* HW mode */ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_SW); -+ if (aspeed_jtag->llops->xfer_hw(aspeed_jtag, xfer, -+ (u32 *)xfer_data) != 0) -+ return -EFAULT; -+ } -+ -+ aspeed_jtag->status = xfer->endstate; -+ return 0; -+} -+ -+static int aspeed_jtag_xfer_hw2(struct aspeed_jtag *aspeed_jtag, -+ struct jtag_xfer *xfer, u32 *data) -+{ -+ unsigned long remain_xfer = xfer->length; -+ unsigned long partial_xfer_size = 0; -+ unsigned long index = 0; -+ u32 shift_bits; -+ u32 data_reg; -+ u32 reg_val; -+ enum jtag_tapstate shift; -+ enum jtag_tapstate exit; -+ u32 start_shift; -+ u32 end_shift; -+ u32 tms_mask; -+ -+ if (xfer->type == JTAG_SIR_XFER) { -+ data_reg = ASPEED_JTAG_SHDATA; -+ shift = JTAG_STATE_SHIFTIR; -+ exit = JTAG_STATE_EXIT1IR; -+ } else { -+ data_reg = ASPEED_JTAG_SHDATA; -+ shift = JTAG_STATE_SHIFTDR; -+ exit = JTAG_STATE_EXIT1DR; -+ } -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, -+ "HW2 JTAG SHIFT %s, length %d from %s to %s then %s stat %s\n", -+ (xfer->type == JTAG_SIR_XFER) ? "IR" : "DR", xfer->length, -+ end_status_str[xfer->from], end_status_str[shift], -+ end_status_str[xfer->endstate], -+ end_status_str[aspeed_jtag->status]); -+#endif -+ -+ if (xfer->from == shift) { -+ start_shift = 0; -+ } else { -+ reg_val = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_GBLCTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ reg_val | ASPEED_JTAG_GBLCTRL_RESET_FIFO, -+ ASPEED_JTAG_GBLCTRL); -+ start_shift = ASPEED_JTAG_SHCTRL_START_SHIFT; -+ } -+ -+ if (xfer->endstate == shift) -+ end_shift = 0; -+ else -+ end_shift = ASPEED_JTAG_SHCTRL_END_SHIFT; -+ -+ while (remain_xfer) { -+ unsigned long partial_xfer; -+ unsigned long partial_index; -+ -+ if (remain_xfer > ASPEED_JTAG_HW2_DATA_CHUNK_SIZE) -+ partial_xfer_size = ASPEED_JTAG_HW2_DATA_CHUNK_SIZE; -+ else -+ partial_xfer_size = remain_xfer; -+ -+ partial_index = index; -+ partial_xfer = partial_xfer_size; -+ while (partial_xfer) { -+ if (partial_xfer > ASPEED_JTAG_DATA_CHUNK_SIZE) -+ shift_bits = ASPEED_JTAG_DATA_CHUNK_SIZE; -+ else -+ shift_bits = partial_xfer; -+ -+ if (xfer->direction & JTAG_WRITE_XFER) -+ aspeed_jtag_write(aspeed_jtag, -+ data[partial_index++], -+ data_reg); -+ else -+ aspeed_jtag_write(aspeed_jtag, 0, data_reg); -+ partial_xfer = partial_xfer - shift_bits; -+ } -+ if (remain_xfer > ASPEED_JTAG_HW2_DATA_CHUNK_SIZE) { -+ shift_bits = ASPEED_JTAG_HW2_DATA_CHUNK_SIZE; -+ -+ /* -+ * Transmit bytes that were not equals to column length -+ * and after the transfer go to Pause IR/DR. -+ */ -+ -+ aspeed_jtag_shctrl_tms_mask(xfer->from, shift, exit, -+ xfer->endstate, start_shift, -+ 0, &tms_mask); -+ -+ reg_val = aspeed_jtag_read(aspeed_jtag, -+ ASPEED_JTAG_GBLCTRL); -+ reg_val = reg_val & ~(GENMASK(22, 20)); -+ aspeed_jtag_write(aspeed_jtag, reg_val | -+ ASPEED_JTAG_GBLCTRL_FIFO_CTRL_MODE | -+ ASPEED_JTAG_GBLCTRL_UPDT_SHIFT( -+ shift_bits), -+ ASPEED_JTAG_GBLCTRL); -+ -+ aspeed_jtag_write(aspeed_jtag, tms_mask | -+ ASPEED_JTAG_SHCTRL_LWRDT_SHIFT(shift_bits), -+ ASPEED_JTAG_SHCTRL); -+ aspeed_jtag_wait_shift_complete(aspeed_jtag); -+ } else { -+ /* -+ * Read bytes equals to column length -+ */ -+ shift_bits = remain_xfer; -+ aspeed_jtag_shctrl_tms_mask(xfer->from, shift, exit, -+ xfer->endstate, start_shift, -+ end_shift, &tms_mask); -+ -+ reg_val = aspeed_jtag_read(aspeed_jtag, -+ ASPEED_JTAG_GBLCTRL); -+ reg_val = reg_val & ~(GENMASK(22, 20)); -+ aspeed_jtag_write(aspeed_jtag, reg_val | -+ ASPEED_JTAG_GBLCTRL_FIFO_CTRL_MODE | -+ ASPEED_JTAG_GBLCTRL_UPDT_SHIFT( -+ shift_bits), -+ ASPEED_JTAG_GBLCTRL); -+ -+ aspeed_jtag_write(aspeed_jtag, tms_mask | -+ ASPEED_JTAG_SHCTRL_LWRDT_SHIFT( -+ shift_bits), -+ ASPEED_JTAG_SHCTRL); -+ -+ aspeed_jtag_wait_shift_complete(aspeed_jtag); -+ } -+ -+ if (xfer->direction & JTAG_READ_XFER) { -+ partial_index = index; -+ partial_xfer = partial_xfer_size; -+ while (partial_xfer) { -+ if (partial_xfer > -+ ASPEED_JTAG_DATA_CHUNK_SIZE) { -+ shift_bits = -+ ASPEED_JTAG_DATA_CHUNK_SIZE; -+ data[partial_index++] = -+ aspeed_jtag_read(aspeed_jtag, -+ data_reg); -+ -+ } else { -+ shift_bits = partial_xfer; -+ data[partial_index++] = -+ aspeed_jtag_read(aspeed_jtag, -+ data_reg); -+ } -+ partial_xfer = partial_xfer - shift_bits; -+ } -+ } -+ -+ remain_xfer = remain_xfer - partial_xfer_size; -+ index = partial_index; -+ start_shift = 0; -+ } -+ aspeed_jtag->status = xfer->endstate; -+ return 0; -+} -+ -+static int aspeed_jtag_status_get(struct jtag *jtag, u32 *status) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+ *status = aspeed_jtag->status; -+ return 0; -+} -+ -+#ifdef USE_INTERRUPTS -+static irqreturn_t aspeed_jtag_interrupt(s32 this_irq, void *dev_id) -+{ -+ struct aspeed_jtag *aspeed_jtag = dev_id; -+ irqreturn_t ret = IRQ_HANDLED; -+ u32 status; -+ -+ status = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_ISR); -+ -+ if (status & ASPEED_JTAG_ISR_INT_MASK) { -+ aspeed_jtag_write(aspeed_jtag, -+ (status & ASPEED_JTAG_ISR_INT_MASK) | -+ (status & -+ ASPEED_JTAG_ISR_INT_EN_MASK), -+ ASPEED_JTAG_ISR); -+ aspeed_jtag->flag |= status & ASPEED_JTAG_ISR_INT_MASK; -+ } -+ -+ if (aspeed_jtag->flag) { -+ wake_up_interruptible(&aspeed_jtag->jtag_wq); -+ ret = IRQ_HANDLED; -+ } else { -+ dev_err(aspeed_jtag->dev, "irq status:%x\n", status); -+ ret = IRQ_NONE; -+ } -+ return ret; -+} -+#endif -+ -+static int aspeed_jtag_enable(struct jtag *jtag) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+ aspeed_jtag->llops->master_enable(aspeed_jtag); -+ return 0; -+} -+ -+static int aspeed_jtag_disable(struct jtag *jtag) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+ aspeed_jtag->llops->output_disable(aspeed_jtag); -+ return 0; -+} -+ -+static int aspeed_jtag_init(struct platform_device *pdev, -+ struct aspeed_jtag *aspeed_jtag) -+{ -+ struct resource *res; -+#ifdef USE_INTERRUPTS -+ int err; -+#endif -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ aspeed_jtag->reg_base = devm_ioremap_resource(aspeed_jtag->dev, res); -+ if (IS_ERR(aspeed_jtag->reg_base)) -+ return -ENOMEM; -+ -+ aspeed_jtag->pclk = devm_clk_get(aspeed_jtag->dev, NULL); -+ if (IS_ERR(aspeed_jtag->pclk)) { -+ dev_err(aspeed_jtag->dev, "devm_clk_get failed\n"); -+ return PTR_ERR(aspeed_jtag->pclk); -+ } -+ -+#ifdef USE_INTERRUPTS -+ aspeed_jtag->irq = platform_get_irq(pdev, 0); -+ if (aspeed_jtag->irq < 0) { -+ dev_err(aspeed_jtag->dev, "no irq specified\n"); -+ return -ENOENT; -+ } -+#endif -+ -+ if (clk_prepare_enable(aspeed_jtag->pclk)) { -+ dev_err(aspeed_jtag->dev, "no irq specified\n"); -+ return -ENOENT; -+ } -+ -+ aspeed_jtag->rst = devm_reset_control_get_shared(&pdev->dev, NULL); -+ if (IS_ERR(aspeed_jtag->rst)) { -+ dev_err(aspeed_jtag->dev, -+ "missing or invalid reset controller device tree entry"); -+ return PTR_ERR(aspeed_jtag->rst); -+ } -+ reset_control_deassert(aspeed_jtag->rst); -+ -+#ifdef USE_INTERRUPTS -+ err = devm_request_irq(aspeed_jtag->dev, aspeed_jtag->irq, -+ aspeed_jtag_interrupt, 0, "aspeed-jtag", -+ aspeed_jtag); -+ if (err) { -+ dev_err(aspeed_jtag->dev, "unable to get IRQ"); -+ clk_disable_unprepare(aspeed_jtag->pclk); -+ return err; -+ } -+#endif -+ -+ aspeed_jtag->llops->output_disable(aspeed_jtag); -+ -+ aspeed_jtag->flag = 0; -+ aspeed_jtag->mode = 0; -+ init_waitqueue_head(&aspeed_jtag->jtag_wq); -+ return 0; -+} -+ -+static int aspeed_jtag_deinit(struct platform_device *pdev, -+ struct aspeed_jtag *aspeed_jtag) -+{ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_ISR); -+ /* Disable clock */ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_CTRL); -+ reset_control_assert(aspeed_jtag->rst); -+ clk_disable_unprepare(aspeed_jtag->pclk); -+ return 0; -+} -+ -+static const struct jtag_ops aspeed_jtag_ops = { -+ .freq_get = aspeed_jtag_freq_get, -+ .freq_set = aspeed_jtag_freq_set, -+ .status_get = aspeed_jtag_status_get, -+ .status_set = aspeed_jtag_status_set, -+ .xfer = aspeed_jtag_xfer, -+ .mode_set = aspeed_jtag_mode_set, -+ .bitbang = aspeed_jtag_bitbang, -+ .enable = aspeed_jtag_enable, -+ .disable = aspeed_jtag_disable -+}; -+ -+static const struct jtag_ops aspeed_jtag_ops_26xx = { -+#ifdef ASPEED_JTAG_HW_MODE_2_ENABLE -+ .freq_get = aspeed_jtag_freq_get_26xx, -+ .freq_set = aspeed_jtag_freq_set_26xx, -+ .status_get = aspeed_jtag_status_get, -+ .status_set = aspeed_jtag_status_set_26xx, -+#else -+ .freq_get = aspeed_jtag_freq_get, -+ .freq_set = aspeed_jtag_freq_set, -+ .status_get = aspeed_jtag_status_get, -+ .status_set = aspeed_jtag_status_set, -+#endif -+ .xfer = aspeed_jtag_xfer, -+ .mode_set = aspeed_jtag_mode_set, -+ .bitbang = aspeed_jtag_bitbang, -+ .enable = aspeed_jtag_enable, -+ .disable = aspeed_jtag_disable -+}; -+ -+static const struct jtag_low_level_functions ast25xx_llops = { -+ .master_enable = aspeed_jtag_master, -+ .output_disable = aspeed_jtag_output_disable, -+ .xfer_push_data = aspeed_jtag_xfer_push_data, -+ .xfer_push_data_last = aspeed_jtag_xfer_push_data_last, -+ .xfer_sw = aspeed_jtag_xfer_sw, -+ .xfer_hw = aspeed_jtag_xfer_hw -+}; -+ -+static const struct aspeed_jtag_functions ast25xx_functions = { -+ .aspeed_jtag_ops = &aspeed_jtag_ops, -+ .aspeed_jtag_llops = &ast25xx_llops -+}; -+ -+static const struct jtag_low_level_functions ast26xx_llops = { -+#ifdef ASPEED_JTAG_HW_MODE_2_ENABLE -+ .master_enable = aspeed_jtag_master_26xx, -+ .output_disable = aspeed_jtag_output_disable_26xx, -+ .xfer_push_data = aspeed_jtag_xfer_push_data_26xx, -+ .xfer_push_data_last = aspeed_jtag_xfer_push_data_last_26xx, -+ .xfer_sw = aspeed_jtag_xfer_sw, -+ .xfer_hw = aspeed_jtag_xfer_hw2 -+#else -+ .master_enable = aspeed_jtag_master, -+ .output_disable = aspeed_jtag_output_disable, -+ .xfer_push_data = aspeed_jtag_xfer_push_data_26xx, -+ .xfer_push_data_last = aspeed_jtag_xfer_push_data_last_26xx, -+ .xfer_sw = aspeed_jtag_xfer_sw, -+ .xfer_hw = aspeed_jtag_xfer_hw -+#endif -+}; -+ -+static const struct aspeed_jtag_functions ast26xx_functions = { -+ .aspeed_jtag_ops = &aspeed_jtag_ops_26xx, -+ .aspeed_jtag_llops = &ast26xx_llops -+}; -+ -+static const struct of_device_id aspeed_jtag_of_match[] = { -+ { .compatible = "aspeed,ast2400-jtag", .data = &ast25xx_functions }, -+ { .compatible = "aspeed,ast2500-jtag", .data = &ast25xx_functions }, -+ { .compatible = "aspeed,ast2600-jtag", .data = &ast26xx_functions }, -+ {} -+}; -+ -+static int aspeed_jtag_probe(struct platform_device *pdev) -+{ -+ struct aspeed_jtag *aspeed_jtag; -+ struct jtag *jtag; -+ const struct of_device_id *match; -+ const struct aspeed_jtag_functions *jtag_functions; -+ int err; -+ -+ match = of_match_node(aspeed_jtag_of_match, pdev->dev.of_node); -+ if (!match) -+ return -ENODEV; -+ jtag_functions = match->data; -+ -+ jtag = jtag_alloc(&pdev->dev, sizeof(*aspeed_jtag), -+ jtag_functions->aspeed_jtag_ops); -+ if (!jtag) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, jtag); -+ aspeed_jtag = jtag_priv(jtag); -+ aspeed_jtag->dev = &pdev->dev; -+ -+ aspeed_jtag->llops = jtag_functions->aspeed_jtag_llops; -+ -+ /* Initialize device*/ -+ err = aspeed_jtag_init(pdev, aspeed_jtag); -+ if (err) -+ goto err_jtag_init; -+ -+ /* Initialize JTAG core structure*/ -+ err = devm_jtag_register(aspeed_jtag->dev, jtag); -+ if (err) -+ goto err_jtag_register; -+ -+ return 0; -+ -+err_jtag_register: -+ aspeed_jtag_deinit(pdev, aspeed_jtag); -+err_jtag_init: -+ jtag_free(jtag); -+ return err; -+} -+ -+static int aspeed_jtag_remove(struct platform_device *pdev) -+{ -+ struct jtag *jtag = platform_get_drvdata(pdev); -+ -+ aspeed_jtag_deinit(pdev, jtag_priv(jtag)); -+ return 0; -+} -+ -+static struct platform_driver aspeed_jtag_driver = { -+ .probe = aspeed_jtag_probe, -+ .remove = aspeed_jtag_remove, -+ .driver = { -+ .name = ASPEED_JTAG_NAME, -+ .of_match_table = aspeed_jtag_of_match, -+ }, -+}; -+module_platform_driver(aspeed_jtag_driver); -+ -+MODULE_AUTHOR("Oleksandr Shamray <oleksandrs@mellanox.com>"); -+MODULE_DESCRIPTION("ASPEED JTAG driver"); -+MODULE_LICENSE("GPL v2"); --- -2.7.4
\ No newline at end of file |