* [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8
@ 2021-01-05 13:44 Tomer Maimon
2021-01-05 13:44 ` [PATCH linux dev-5.8 v2 01/11] clk: npcm7xx: add read only flag to divider clocks Tomer Maimon
` (11 more replies)
0 siblings, 12 replies; 20+ messages in thread
From: Tomer Maimon @ 2021-01-05 13:44 UTC (permalink / raw)
To: openbmc; +Cc: Andrew Jeffery, Tomer Maimon, benjaminfair
In this patch set we will like to align with relevant modifications
in Nuvoton OpenBMC Linux kernel 5.4.
Linux upstream current status:
1. npcm7xx clock driver - adding read only
flag to divider clocks, Will be sent to Linux community.
2. Adding NPCM ADC calibration - Will be sent to Linux vanilla,
but I am not sure it will be approved.
3. Add DT restart priority and reset type support - sent to Linux
community la but havent approved yet.
4. persist configuration to the pin control driver - asked by a costumer,
didnt sent to Linux community.
5. Add HGPIO pin support to NPCM7xx pinctrl driver - will be sent
to Linux community
6. JTAG master driver - will be sent to Linux community once we will
have BMC folder.
Changes since version 1:
- Address comments from Jonathan Neuschäfer: removing trailing whitespace
in NPCM watchdog documentation.
- Adding Stanley Chu to NPCM JTAG master driver
Tomer Maimon (11):
clk: npcm7xx: add read only flag to divider clocks
iio: adc: add calibration support to npcm ADC
dts: npcm750: add fuse regmap support node
watchdog: npcm: Add DT restart priority and reset type support
dt-binding: watchdog: Add DT restart priority and reset type
pinctrl: npcm7xx: Add HGPIO pin support to NPCM7xx pinctrl driver
pinctrl: pinconf: add pin persist configuration
pinctrl: npcm7xx: Add pin persist configuration support
spi: npcm-pspi: Add full duplex support
dt-binding: bmc: add NPCM7XX JTAG master documentation
misc: npcm7xx-jtag-master: add NPCM7xx JTAG master driver
.../bindings/bmc/npcm7xx-jtag-master.txt | 38 +
.../bindings/watchdog/nuvoton,npcm-wdt.txt | 32 +
arch/arm/boot/dts/nuvoton-common-npcm7xx.dtsi | 6 +
drivers/clk/clk-npcm7xx.c | 70 +-
drivers/iio/adc/npcm_adc.c | 191 ++++
drivers/misc/Kconfig | 6 +
drivers/misc/Makefile | 1 +
drivers/misc/npcm7xx-jtag-master.c | 840 ++++++++++++++++++
drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c | 130 ++-
drivers/pinctrl/pinconf-generic.c | 3 +
drivers/spi/spi-npcm-pspi.c | 75 +-
drivers/watchdog/npcm_wdt.c | 121 ++-
12 files changed, 1418 insertions(+), 95 deletions(-)
create mode 100644 Documentation/devicetree/bindings/bmc/npcm7xx-jtag-master.txt
create mode 100644 drivers/misc/npcm7xx-jtag-master.c
--
2.22.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH linux dev-5.8 v2 01/11] clk: npcm7xx: add read only flag to divider clocks
2021-01-05 13:44 [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Tomer Maimon
@ 2021-01-05 13:44 ` Tomer Maimon
2021-01-05 13:44 ` [PATCH linux dev-5.8 v2 02/11] iio: adc: add calibration support to npcm ADC Tomer Maimon
` (10 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Tomer Maimon @ 2021-01-05 13:44 UTC (permalink / raw)
To: openbmc; +Cc: Andrew Jeffery, Tomer Maimon, benjaminfair
Add read only flag to all divider clocks except
SPI3 clock.
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
drivers/clk/clk-npcm7xx.c | 70 +++++++++++++++++++++------------------
1 file changed, 38 insertions(+), 32 deletions(-)
diff --git a/drivers/clk/clk-npcm7xx.c b/drivers/clk/clk-npcm7xx.c
index 27a86b7a34db..bf721ec2bbc6 100644
--- a/drivers/clk/clk-npcm7xx.c
+++ b/drivers/clk/clk-npcm7xx.c
@@ -370,67 +370,73 @@ static const struct npcm7xx_clk_div_fixed_data npcm7xx_divs_fx[] __initconst = {
/* configurable dividers: */
static const struct npcm7xx_clk_div_data npcm7xx_divs[] __initconst = {
- {NPCM7XX_CLKDIV1, 28, 3, NPCM7XX_CLK_S_ADC,
- NPCM7XX_CLK_S_TIMER, CLK_DIVIDER_POWER_OF_TWO, 0, NPCM7XX_CLK_ADC},
+ {NPCM7XX_CLKDIV1, 28, 3, NPCM7XX_CLK_S_ADC, NPCM7XX_CLK_S_TIMER,
+ CLK_DIVIDER_READ_ONLY | CLK_DIVIDER_POWER_OF_TWO, 0,
+ NPCM7XX_CLK_ADC},
/*30-28 ADCCKDIV*/
- {NPCM7XX_CLKDIV1, 26, 2, NPCM7XX_CLK_S_AHB,
- NPCM7XX_CLK_S_AXI, 0, CLK_IS_CRITICAL, NPCM7XX_CLK_AHB},
+ {NPCM7XX_CLKDIV1, 26, 2, NPCM7XX_CLK_S_AHB, NPCM7XX_CLK_S_AXI,
+ CLK_DIVIDER_READ_ONLY, CLK_IS_CRITICAL, NPCM7XX_CLK_AHB},
/*27-26 CLK4DIV*/
{NPCM7XX_CLKDIV1, 21, 5, NPCM7XX_CLK_S_TIMER,
- NPCM7XX_CLK_S_TIM_MUX, 0, 0, NPCM7XX_CLK_TIMER},
+ NPCM7XX_CLK_S_TIM_MUX, CLK_DIVIDER_READ_ONLY, 0, NPCM7XX_CLK_TIMER},
/*25-21 TIMCKDIV*/
{NPCM7XX_CLKDIV1, 16, 5, NPCM7XX_CLK_S_UART,
- NPCM7XX_CLK_S_UART_MUX, 0, 0, NPCM7XX_CLK_UART},
+ NPCM7XX_CLK_S_UART_MUX, CLK_DIVIDER_READ_ONLY, 0, NPCM7XX_CLK_UART},
/*20-16 UARTDIV*/
{NPCM7XX_CLKDIV1, 11, 5, NPCM7XX_CLK_S_MMC,
- NPCM7XX_CLK_S_SD_MUX, 0, 0, NPCM7XX_CLK_MMC},
+ NPCM7XX_CLK_S_SD_MUX, CLK_DIVIDER_READ_ONLY, 0, NPCM7XX_CLK_MMC},
/*15-11 MMCCKDIV*/
{NPCM7XX_CLKDIV1, 6, 5, NPCM7XX_CLK_S_SPI3,
NPCM7XX_CLK_S_AHB, 0, 0, NPCM7XX_CLK_SPI3},
/*10-6 AHB3CKDIV*/
{NPCM7XX_CLKDIV1, 2, 4, NPCM7XX_CLK_S_PCI,
- NPCM7XX_CLK_S_GFX_MUX, 0, 0, NPCM7XX_CLK_PCI},
+ NPCM7XX_CLK_S_GFX_MUX, CLK_DIVIDER_READ_ONLY, 0, NPCM7XX_CLK_PCI},
/*5-2 PCICKDIV*/
- {NPCM7XX_CLKDIV1, 0, 1, NPCM7XX_CLK_S_AXI,
- NPCM7XX_CLK_S_CPU_MUX, CLK_DIVIDER_POWER_OF_TWO, CLK_IS_CRITICAL,
- NPCM7XX_CLK_AXI},/*0 CLK2DIV*/
+ {NPCM7XX_CLKDIV1, 0, 1, NPCM7XX_CLK_S_AXI, NPCM7XX_CLK_S_CPU_MUX,
+ CLK_DIVIDER_READ_ONLY | CLK_DIVIDER_POWER_OF_TWO,
+ CLK_IS_CRITICAL, NPCM7XX_CLK_AXI},/*0 CLK2DIV*/
- {NPCM7XX_CLKDIV2, 30, 2, NPCM7XX_CLK_S_APB4,
- NPCM7XX_CLK_S_AHB, CLK_DIVIDER_POWER_OF_TWO, 0, NPCM7XX_CLK_APB4},
+ {NPCM7XX_CLKDIV2, 30, 2, NPCM7XX_CLK_S_APB4, NPCM7XX_CLK_S_AHB,
+ CLK_DIVIDER_READ_ONLY| CLK_DIVIDER_POWER_OF_TWO, 0,
+ NPCM7XX_CLK_APB4},
/*31-30 APB4CKDIV*/
- {NPCM7XX_CLKDIV2, 28, 2, NPCM7XX_CLK_S_APB3,
- NPCM7XX_CLK_S_AHB, CLK_DIVIDER_POWER_OF_TWO, 0, NPCM7XX_CLK_APB3},
+ {NPCM7XX_CLKDIV2, 28, 2, NPCM7XX_CLK_S_APB3, NPCM7XX_CLK_S_AHB,
+ CLK_DIVIDER_READ_ONLY| CLK_DIVIDER_POWER_OF_TWO, 0,
+ NPCM7XX_CLK_APB3},
/*29-28 APB3CKDIV*/
- {NPCM7XX_CLKDIV2, 26, 2, NPCM7XX_CLK_S_APB2,
- NPCM7XX_CLK_S_AHB, CLK_DIVIDER_POWER_OF_TWO, 0, NPCM7XX_CLK_APB2},
+ {NPCM7XX_CLKDIV2, 26, 2, NPCM7XX_CLK_S_APB2, NPCM7XX_CLK_S_AHB,
+ CLK_DIVIDER_READ_ONLY | CLK_DIVIDER_POWER_OF_TWO, 0,
+ NPCM7XX_CLK_APB2},
/*27-26 APB2CKDIV*/
- {NPCM7XX_CLKDIV2, 24, 2, NPCM7XX_CLK_S_APB1,
- NPCM7XX_CLK_S_AHB, CLK_DIVIDER_POWER_OF_TWO, 0, NPCM7XX_CLK_APB1},
+ {NPCM7XX_CLKDIV2, 24, 2, NPCM7XX_CLK_S_APB1, NPCM7XX_CLK_S_AHB,
+ CLK_DIVIDER_READ_ONLY | CLK_DIVIDER_POWER_OF_TWO, 0,
+ NPCM7XX_CLK_APB1},
/*25-24 APB1CKDIV*/
- {NPCM7XX_CLKDIV2, 22, 2, NPCM7XX_CLK_S_APB5,
- NPCM7XX_CLK_S_AHB, CLK_DIVIDER_POWER_OF_TWO, 0, NPCM7XX_CLK_APB5},
+ {NPCM7XX_CLKDIV2, 22, 2, NPCM7XX_CLK_S_APB5, NPCM7XX_CLK_S_AHB,
+ CLK_DIVIDER_READ_ONLY | CLK_DIVIDER_POWER_OF_TWO, 0,
+ NPCM7XX_CLK_APB5},
/*23-22 APB5CKDIV*/
- {NPCM7XX_CLKDIV2, 16, 5, NPCM7XX_CLK_S_CLKOUT,
- NPCM7XX_CLK_S_CLKOUT_MUX, 0, 0, NPCM7XX_CLK_CLKOUT},
+ {NPCM7XX_CLKDIV2, 16, 5, NPCM7XX_CLK_S_CLKOUT, NPCM7XX_CLK_S_CLKOUT_MUX,
+ CLK_DIVIDER_READ_ONLY, 0, NPCM7XX_CLK_CLKOUT},
/*20-16 CLKOUTDIV*/
- {NPCM7XX_CLKDIV2, 13, 3, NPCM7XX_CLK_S_GFX,
- NPCM7XX_CLK_S_GFX_MUX, 0, 0, NPCM7XX_CLK_GFX},
+ {NPCM7XX_CLKDIV2, 13, 3, NPCM7XX_CLK_S_GFX, NPCM7XX_CLK_S_GFX_MUX,
+ CLK_DIVIDER_READ_ONLY, 0, NPCM7XX_CLK_GFX},
/*15-13 GFXCKDIV*/
- {NPCM7XX_CLKDIV2, 8, 5, NPCM7XX_CLK_S_USB_BRIDGE,
- NPCM7XX_CLK_S_SU_MUX, 0, 0, NPCM7XX_CLK_SU},
+ {NPCM7XX_CLKDIV2, 8, 5, NPCM7XX_CLK_S_USB_BRIDGE, NPCM7XX_CLK_S_SU_MUX,
+ CLK_DIVIDER_READ_ONLY, 0, NPCM7XX_CLK_SU},
/*12-8 SUCKDIV*/
- {NPCM7XX_CLKDIV2, 4, 4, NPCM7XX_CLK_S_USB_HOST,
- NPCM7XX_CLK_S_SU_MUX, 0, 0, NPCM7XX_CLK_SU48},
+ {NPCM7XX_CLKDIV2, 4, 4, NPCM7XX_CLK_S_USB_HOST, NPCM7XX_CLK_S_SU_MUX,
+ CLK_DIVIDER_READ_ONLY, 0, NPCM7XX_CLK_SU48},
/*7-4 SU48CKDIV*/
{NPCM7XX_CLKDIV2, 0, 4, NPCM7XX_CLK_S_SDHC,
- NPCM7XX_CLK_S_SD_MUX, 0, 0, NPCM7XX_CLK_SDHC}
+ NPCM7XX_CLK_S_SD_MUX, CLK_DIVIDER_READ_ONLY, 0, NPCM7XX_CLK_SDHC}
,/*3-0 SD1CKDIV*/
{NPCM7XX_CLKDIV3, 6, 5, NPCM7XX_CLK_S_SPI0,
- NPCM7XX_CLK_S_AHB, 0, 0, NPCM7XX_CLK_SPI0},
+ NPCM7XX_CLK_S_AHB, CLK_DIVIDER_READ_ONLY, 0, NPCM7XX_CLK_SPI0},
/*10-6 SPI0CKDV*/
{NPCM7XX_CLKDIV3, 1, 5, NPCM7XX_CLK_S_SPIX,
- NPCM7XX_CLK_S_AHB, 0, 0, NPCM7XX_CLK_SPIX},
+ NPCM7XX_CLK_S_AHB, CLK_DIVIDER_READ_ONLY, 0, NPCM7XX_CLK_SPIX},
/*5-1 SPIXCKDV*/
};
--
2.22.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH linux dev-5.8 v2 02/11] iio: adc: add calibration support to npcm ADC
2021-01-05 13:44 [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Tomer Maimon
2021-01-05 13:44 ` [PATCH linux dev-5.8 v2 01/11] clk: npcm7xx: add read only flag to divider clocks Tomer Maimon
@ 2021-01-05 13:44 ` Tomer Maimon
2021-01-11 0:52 ` Joel Stanley
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 03/11] dts: npcm750: add fuse regmap support node Tomer Maimon
` (9 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: Tomer Maimon @ 2021-01-05 13:44 UTC (permalink / raw)
To: openbmc; +Cc: Andrew Jeffery, Tomer Maimon, benjaminfair
Add calibration to improve accuracy measurement when using
internal referance voltage.
the calibration values taken from the FUSE module.
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
drivers/iio/adc/npcm_adc.c | 191 +++++++++++++++++++++++++++++++++++++
1 file changed, 191 insertions(+)
diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c
index 83bad2d5575d..02628b7eaca1 100644
--- a/drivers/iio/adc/npcm_adc.c
+++ b/drivers/iio/adc/npcm_adc.c
@@ -17,6 +17,8 @@
#include <linux/reset.h>
struct npcm_adc {
+ u32 R05;
+ u32 R15;
bool int_status;
u32 adc_sample_hz;
struct device *dev;
@@ -51,6 +53,40 @@ struct npcm_adc {
#define NPCM_RESOLUTION_BITS 10
#define NPCM_INT_VREF_MV 2000
+/* FUSE registers */
+#define NPCM7XX_FST 0x00
+#define NPCM7XX_FADDR 0x04
+#define NPCM7XX_FDATA 0x08
+#define NPCM7XX_FCFG 0x0C
+#define NPCM7XX_FCTL 0x14
+
+/* FST Register Bits */
+#define NPCM7XX_FST_RDY BIT(0)
+#define NPCM7XX_FST_RDST BIT(1)
+
+/* FADDR Register Bits */
+#define NPCM7XX_FADDR_BYTEADDR BIT(0)
+#define NPCM7XX_FADDR_BYTEADDR_MASK GENMASK(9, 0)
+
+/* FADDR Register Bits */
+#define NPCM7XX_FDATA_DATA BIT(0)
+#define NPCM7XX_FDATA_CLEAN_VALUE BIT(1)
+#define NPCM7XX_FDATA_DATA_MASK GENMASK(7, 0)
+
+/* FCTL Register Bits */
+#define NPCM7XX_FCTL_RDST BIT(1)
+
+/* ADC Calibration Definition */
+#define NPCM_INT_1500MV 768
+#define NPCM_INT_1000MV 512
+#define NPCM_ADC_MIN_VAL 0
+#define NPCM_ADC_MAX_VAL 1023
+
+#define FUSE_CALIB_ADDR 24
+#define FUSE_CALIB_SIZE 8
+#define DATA_CALIB_SIZE 4
+#define FUSE_READ_TIMEOUT 0xDEADBEEF
+
#define NPCM_ADC_CHAN(ch) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
@@ -71,6 +107,133 @@ static const struct iio_chan_spec npcm_adc_iio_channels[] = {
NPCM_ADC_CHAN(7),
};
+static int npcm750_fuse_wait_for_ready(struct regmap *fuse_regmap, u32 timeout)
+{
+ u32 time = timeout;
+ u32 fstreg;
+
+ while (--time > 1) {
+ regmap_read(fuse_regmap, NPCM7XX_FST, &fstreg);
+ if (fstreg & NPCM7XX_FST_RDY) {
+ regmap_write_bits(fuse_regmap, NPCM7XX_FST,
+ NPCM7XX_FST_RDST, NPCM7XX_FST_RDST);
+ return 0;
+ }
+ }
+
+ /* try to clear the status in case it was set */
+ regmap_write_bits(fuse_regmap, NPCM7XX_FST, NPCM7XX_FST_RDST,
+ NPCM7XX_FST_RDST);
+
+ return -EINVAL;
+}
+
+static void npcm750_fuse_read(struct regmap *fuse_regmap, u32 addr, u8 *data)
+{
+ u32 val;
+
+ npcm750_fuse_wait_for_ready(fuse_regmap, FUSE_READ_TIMEOUT);
+
+ regmap_write_bits(fuse_regmap, NPCM7XX_FADDR,
+ NPCM7XX_FADDR_BYTEADDR_MASK, addr);
+ regmap_read(fuse_regmap, NPCM7XX_FADDR, &val);
+ regmap_write(fuse_regmap, NPCM7XX_FCTL, NPCM7XX_FCTL_RDST);
+
+ npcm750_fuse_wait_for_ready(fuse_regmap, FUSE_READ_TIMEOUT);
+ regmap_read(fuse_regmap, NPCM7XX_FDATA, &val);
+ *data = (u8)val;
+
+ regmap_write_bits(fuse_regmap, NPCM7XX_FDATA, NPCM7XX_FDATA_DATA_MASK,
+ NPCM7XX_FDATA_CLEAN_VALUE);
+}
+
+static int npcm750_ECC_to_nibble(u8 ECC, u8 nibble)
+{
+ u8 nibble_b0 = (nibble >> 0) & BIT(0);
+ u8 nibble_b1 = (nibble >> 1) & BIT(0);
+ u8 nibble_b2 = (nibble >> 2) & BIT(0);
+ u8 nibble_b3 = (nibble >> 3) & BIT(0);
+ u8 tmp_ECC = nibble;
+
+ tmp_ECC |= (nibble_b0 ^ nibble_b1) << 4 | (nibble_b2 ^ nibble_b3) << 5 |
+ (nibble_b0 ^ nibble_b2) << 6 | (nibble_b1 ^ nibble_b3) << 7;
+
+ if (tmp_ECC != ECC)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int npcm750_ECC_to_byte(u16 ECC, u8 *Byte)
+{
+ u8 nibble_L, nibble_H;
+ u8 ECC_L, ECC_H;
+
+ ECC_H = ECC >> 8;
+ nibble_H = ECC_H & 0x0F;
+ ECC_L = ECC >> 0;
+ nibble_L = ECC_L & 0x0F;
+
+ if (npcm750_ECC_to_nibble(ECC_H, nibble_H) != 0 ||
+ npcm750_ECC_to_nibble(ECC_L, nibble_L) != 0)
+ return -EINVAL;
+
+ *Byte = nibble_H << 4 | nibble_L << 0;
+
+ return 0;
+}
+
+static int npcm750_read_nibble_parity(u8 *block_ECC, u8 *ADC_calib)
+{
+ int i;
+ u16 ECC;
+
+ for (i = 0; i < DATA_CALIB_SIZE; i++) {
+ memcpy(&ECC, block_ECC + (i * 2), 2);
+ if (npcm750_ECC_to_byte(ECC, &ADC_calib[i]) != 0)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int npcm750_fuse_calibration_read(struct platform_device *pdev,
+ struct npcm_adc *info)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct regmap *fuse_regmap;
+ ssize_t bytes_read = 0;
+ u8 read_buf[8];
+ u32 ADC_calib;
+ u32 addr = FUSE_CALIB_ADDR;
+
+ if (of_device_is_compatible(np, "nuvoton,npcm750-adc")) {
+ fuse_regmap = syscon_regmap_lookup_by_compatible
+ ("nuvoton,npcm750-fuse");
+ if (IS_ERR(fuse_regmap)) {
+ dev_warn(&pdev->dev, "Failed to find nuvoton,npcm750-fuse\n");
+ return PTR_ERR(fuse_regmap);
+ }
+
+ while (bytes_read < FUSE_CALIB_SIZE) {
+ npcm750_fuse_read(fuse_regmap, addr,
+ &read_buf[bytes_read]);
+ bytes_read++;
+ addr++;
+ }
+
+ if (npcm750_read_nibble_parity(read_buf, (u8 *)&ADC_calib)) {
+ dev_warn(info->dev, "FUSE Clibration read failed\n");
+ return -EINVAL;
+ }
+
+ info->R05 = ADC_calib & 0xFFFF;
+ info->R15 = ADC_calib >> 16;
+ }
+
+ return 0;
+}
+
static irqreturn_t npcm_adc_isr(int irq, void *data)
{
u32 regtemp;
@@ -125,6 +288,29 @@ static int npcm_adc_read(struct npcm_adc *info, int *val, u8 channel)
return 0;
}
+static void npcm_adc_calibration(int *val, struct npcm_adc *info)
+{
+ int mul_val;
+ int offset_val;
+
+ mul_val = NPCM_INT_1000MV * (*val - info->R15);
+ if (mul_val < 0) {
+ mul_val = mul_val * -1;
+ offset_val = DIV_ROUND_CLOSEST(mul_val,
+ (info->R15 - info->R05));
+ *val = NPCM_INT_1500MV - offset_val;
+ } else {
+ offset_val = DIV_ROUND_CLOSEST(mul_val,
+ (info->R15 - info->R05));
+ *val = NPCM_INT_1500MV + offset_val;
+ }
+
+ if (*val < NPCM_ADC_MIN_VAL)
+ *val = NPCM_ADC_MIN_VAL;
+ if (*val > NPCM_ADC_MAX_VAL)
+ *val = NPCM_ADC_MAX_VAL;
+}
+
static int npcm_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
@@ -142,6 +328,10 @@ static int npcm_adc_read_raw(struct iio_dev *indio_dev,
dev_err(info->dev, "NPCM ADC read failed\n");
return ret;
}
+
+ if ((info->R05 || info->R15) && IS_ERR(info->vref))
+ npcm_adc_calibration(val, info);
+
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
if (!IS_ERR(info->vref)) {
@@ -248,6 +438,7 @@ static int npcm_adc_probe(struct platform_device *pdev)
info->regs + NPCM_ADCCON);
}
+ npcm750_fuse_calibration_read(pdev, info);
init_waitqueue_head(&info->wq);
reg_con = ioread32(info->regs + NPCM_ADCCON);
--
2.22.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH linux dev-5.8 v2 03/11] dts: npcm750: add fuse regmap support node
2021-01-05 13:44 [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Tomer Maimon
2021-01-05 13:44 ` [PATCH linux dev-5.8 v2 01/11] clk: npcm7xx: add read only flag to divider clocks Tomer Maimon
2021-01-05 13:44 ` [PATCH linux dev-5.8 v2 02/11] iio: adc: add calibration support to npcm ADC Tomer Maimon
@ 2021-01-05 13:45 ` Tomer Maimon
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 04/11] watchdog: npcm: Add DT restart priority and reset type support Tomer Maimon
` (8 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Tomer Maimon @ 2021-01-05 13:45 UTC (permalink / raw)
To: openbmc; +Cc: Andrew Jeffery, Tomer Maimon, benjaminfair
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
arch/arm/boot/dts/nuvoton-common-npcm7xx.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm/boot/dts/nuvoton-common-npcm7xx.dtsi b/arch/arm/boot/dts/nuvoton-common-npcm7xx.dtsi
index 7eee4145127f..455a96b23b85 100644
--- a/arch/arm/boot/dts/nuvoton-common-npcm7xx.dtsi
+++ b/arch/arm/boot/dts/nuvoton-common-npcm7xx.dtsi
@@ -82,6 +82,12 @@
"simple-mfd";
reg = <0x801000 0x6C>;
};
+
+ fuse:fuse@18a000 {
+ compatible = "nuvoton,npcm750-fuse", "syscon",
+ "simple-mfd";
+ reg = <0x18a000 0x1000>;
+ };
scu: scu@3fe000 {
compatible = "arm,cortex-a9-scu";
--
2.22.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH linux dev-5.8 v2 04/11] watchdog: npcm: Add DT restart priority and reset type support
2021-01-05 13:44 [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Tomer Maimon
` (2 preceding siblings ...)
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 03/11] dts: npcm750: add fuse regmap support node Tomer Maimon
@ 2021-01-05 13:45 ` Tomer Maimon
2021-01-11 0:55 ` Joel Stanley
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 05/11] dt-binding: watchdog: Add DT restart priority and reset type Tomer Maimon
` (7 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: Tomer Maimon @ 2021-01-05 13:45 UTC (permalink / raw)
To: openbmc; +Cc: Andrew Jeffery, Tomer Maimon, benjaminfair
Add Device tree restart priority and
three reset types support.
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
drivers/watchdog/npcm_wdt.c | 121 +++++++++++++++++++++++++++++++++++-
1 file changed, 119 insertions(+), 2 deletions(-)
diff --git a/drivers/watchdog/npcm_wdt.c b/drivers/watchdog/npcm_wdt.c
index 765577f11c8d..bbf27da34834 100644
--- a/drivers/watchdog/npcm_wdt.c
+++ b/drivers/watchdog/npcm_wdt.c
@@ -11,7 +11,24 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/watchdog.h>
-
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+/* NPCM7xx GCR module */
+#define NPCM7XX_RESSR_OFFSET 0x6C
+#define NPCM7XX_INTCR2_OFFSET 0x60
+
+#define NPCM7XX_PORST BIT(31)
+#define NPCM7XX_CORST BIT(30)
+#define NPCM7XX_WD0RST BIT(29)
+#define NPCM7XX_WD1RST BIT(24)
+#define NPCM7XX_WD2RST BIT(23)
+#define NPCM7XX_SWR1RST BIT(28)
+#define NPCM7XX_SWR2RST BIT(27)
+#define NPCM7XX_SWR3RST BIT(26)
+#define NPCM7XX_SWR4RST BIT(25)
+
+ /* WD register */
#define NPCM_WTCR 0x1C
#define NPCM_WTCLK (BIT(10) | BIT(11)) /* Clock divider */
@@ -43,6 +60,10 @@
struct npcm_wdt {
struct watchdog_device wdd;
void __iomem *reg;
+ u32 card_reset;
+ u32 ext1_reset;
+ u32 ext2_reset;
+
};
static inline struct npcm_wdt *to_npcm_wdt(struct watchdog_device *wdd)
@@ -176,14 +197,70 @@ static const struct watchdog_ops npcm_wdt_ops = {
.restart = npcm_wdt_restart,
};
+static void npcm_get_reset_status(struct npcm_wdt *wdt, struct device *dev)
+{
+ struct regmap *gcr_regmap;
+ u32 rstval;
+
+ if (of_device_is_compatible(dev->of_node, "nuvoton,npcm750-wdt")) {
+ gcr_regmap = syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr");
+ if (IS_ERR(gcr_regmap)) {
+ dev_warn(dev, "Failed to find nuvoton,npcm750-gcr WD reset status not supported\n");
+ }
+
+ regmap_read(gcr_regmap, NPCM7XX_RESSR_OFFSET, &rstval);
+ if (!rstval) {
+ regmap_read(gcr_regmap, NPCM7XX_INTCR2_OFFSET, &rstval);
+ rstval = ~rstval;
+ }
+
+ if(rstval & wdt->card_reset)
+ wdt->wdd.bootstatus |= WDIOF_CARDRESET;
+ if(rstval & wdt->ext1_reset)
+ wdt->wdd.bootstatus |= WDIOF_EXTERN1;
+ if(rstval & wdt->ext2_reset)
+ wdt->wdd.bootstatus |= WDIOF_EXTERN2;
+ }
+
+}
+
+static u32 npcm_wdt_reset_type(const char *reset_type)
+{
+ if (!strcmp(reset_type, "porst"))
+ return NPCM7XX_PORST;
+ else if (!strcmp(reset_type, "corst"))
+ return NPCM7XX_CORST;
+ else if (!strcmp(reset_type, "wd0"))
+ return NPCM7XX_WD0RST;
+ else if (!strcmp(reset_type, "wd1"))
+ return NPCM7XX_WD1RST;
+ else if (!strcmp(reset_type, "wd2"))
+ return NPCM7XX_WD2RST;
+ else if (!strcmp(reset_type, "sw1"))
+ return NPCM7XX_SWR1RST;
+ else if (!strcmp(reset_type, "sw2"))
+ return NPCM7XX_SWR2RST;
+ else if (!strcmp(reset_type, "sw3"))
+ return NPCM7XX_SWR3RST;
+ else if (!strcmp(reset_type, "sw4"))
+ return NPCM7XX_SWR4RST;
+
+ return 0;
+}
+
static int npcm_wdt_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ const char *card_reset_type;
+ const char *ext1_reset_type;
+ const char *ext2_reset_type;
struct npcm_wdt *wdt;
+ struct resource *res;
+ u32 priority;
int irq;
int ret;
- wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
+ wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
if (!wdt)
return -ENOMEM;
@@ -195,6 +272,45 @@ static int npcm_wdt_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
+ if (of_property_read_u32(pdev->dev.of_node, "nuvoton,restart-priority",
+ &priority))
+ watchdog_set_restart_priority(&wdt->wdd, 128);
+ else
+ watchdog_set_restart_priority(&wdt->wdd, priority);
+
+ ret = of_property_read_string(pdev->dev.of_node,
+ "nuvoton,card-reset-type",
+ &card_reset_type);
+ if (ret)
+ wdt->card_reset = NPCM7XX_PORST;
+ else {
+ wdt->card_reset = npcm_wdt_reset_type(card_reset_type);
+ if (!wdt->card_reset)
+ wdt->card_reset = NPCM7XX_PORST;
+ }
+
+ ret = of_property_read_string(pdev->dev.of_node,
+ "nuvoton,ext1-reset-type",
+ &ext1_reset_type);
+ if (ret)
+ wdt->ext1_reset = NPCM7XX_WD0RST;
+ else {
+ wdt->ext1_reset = npcm_wdt_reset_type(ext1_reset_type);
+ if (!wdt->ext1_reset)
+ wdt->ext1_reset = NPCM7XX_WD0RST;
+ }
+
+ ret = of_property_read_string(pdev->dev.of_node,
+ "nuvoton,ext2-reset-type",
+ &ext2_reset_type);
+ if (ret)
+ wdt->ext2_reset = NPCM7XX_SWR1RST;
+ else {
+ wdt->ext2_reset = npcm_wdt_reset_type(ext2_reset_type);
+ if (!wdt->ext2_reset)
+ wdt->ext2_reset = NPCM7XX_SWR1RST;
+ }
+
wdt->wdd.info = &npcm_wdt_info;
wdt->wdd.ops = &npcm_wdt_ops;
wdt->wdd.min_timeout = 1;
@@ -213,6 +329,7 @@ static int npcm_wdt_probe(struct platform_device *pdev)
set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
}
+ npcm_get_reset_status(wdt, dev);
ret = devm_request_irq(dev, irq, npcm_wdt_interrupt, 0, "watchdog",
wdt);
if (ret)
--
2.22.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH linux dev-5.8 v2 05/11] dt-binding: watchdog: Add DT restart priority and reset type
2021-01-05 13:44 [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Tomer Maimon
` (3 preceding siblings ...)
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 04/11] watchdog: npcm: Add DT restart priority and reset type support Tomer Maimon
@ 2021-01-05 13:45 ` Tomer Maimon
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 06/11] pinctrl: npcm7xx: Add HGPIO pin support to NPCM7xx pinctrl driver Tomer Maimon
` (6 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Tomer Maimon @ 2021-01-05 13:45 UTC (permalink / raw)
To: openbmc; +Cc: Andrew Jeffery, Tomer Maimon, benjaminfair
Add device tree restart priority documentation and
three reset types documentation.
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
.../bindings/watchdog/nuvoton,npcm-wdt.txt | 32 +++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/Documentation/devicetree/bindings/watchdog/nuvoton,npcm-wdt.txt b/Documentation/devicetree/bindings/watchdog/nuvoton,npcm-wdt.txt
index 6d593003c933..f6e0ea3e3c78 100644
--- a/Documentation/devicetree/bindings/watchdog/nuvoton,npcm-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/nuvoton,npcm-wdt.txt
@@ -17,6 +17,34 @@ Required clocking property, have to be one of:
Optional properties:
- timeout-sec : Contains the watchdog timeout in seconds
+- nuvoton,restart-priority - Contains the card restart priority.
+- nuvoton,card-reset-type = "porst|corst|wd0|wd1|wd2|sw1|sw2|sw3|sw4"
+ Contains the card reset type for checking and indicating
+ the last card reset status (WDIOF_CARDRESET)
+
+ If 'nuvoton,card-reset-type' is not specified the default is porst
+
+ Reset types:
+ - porst: Power reset
+ - corst: Core reset
+ - wdX : Watchdog reset X (X represante 0-2)
+ - swX : Software reset X (X represante 1-4)
+
+- nuvoton,ext1-reset-type = "porst|corst|wd0|wd1|wd2|sw1|sw2|sw3|sw4"
+ Contains the external 2 reset type for checking and indicating
+ the last external 2 reset status (WDIOF_EXTERN1)
+
+ If 'nuvoton,card-reset-type' is not specified the default is wd0.
+
+ Reset types are the same as in nuvoton,card-reset-type property.
+
+- nuvoton,ext2-reset-type = "porst|corst|wd0|wd1|wd2|sw1|sw2|sw3|sw4"
+ Contains the external 2 reset type for checking and indicating
+ the last external 2 reset status (WDIOF_EXTERN2)
+
+ If 'nuvoton,card-reset-type' is not specified the default is sw1.
+
+ Reset types are the same as in nuvoton,card-reset-type property.
Example:
@@ -25,4 +53,8 @@ timer@f000801c {
interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
reg = <0xf000801c 0x4>;
clocks = <&clk NPCM7XX_CLK_TIMER>;
+ nuvoton,restart-priority = <155>;
+ nuvoton,card-reset-type = "porst";
+ nuvoton,ext1-reset-type = "wd1";
+ nuvoton,ext2-reset-type = "sw2";
};
--
2.22.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH linux dev-5.8 v2 06/11] pinctrl: npcm7xx: Add HGPIO pin support to NPCM7xx pinctrl driver
2021-01-05 13:44 [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Tomer Maimon
` (4 preceding siblings ...)
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 05/11] dt-binding: watchdog: Add DT restart priority and reset type Tomer Maimon
@ 2021-01-05 13:45 ` Tomer Maimon
2021-01-11 0:56 ` Joel Stanley
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 07/11] pinctrl: pinconf: add pin persist configuration Tomer Maimon
` (5 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: Tomer Maimon @ 2021-01-05 13:45 UTC (permalink / raw)
To: openbmc; +Cc: Andrew Jeffery, Tomer Maimon, benjaminfair
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c | 65 +++++++++++++++++------
1 file changed, 49 insertions(+), 16 deletions(-)
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
index a935065cdac4..e5f58ea89917 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
@@ -504,6 +504,15 @@ static const int lkgpo2_pins[] = { 9 };
static const int nprd_smi_pins[] = { 190 };
+static const int hgpio0_pins[] = { 20 };
+static const int hgpio1_pins[] = { 21 };
+static const int hgpio2_pins[] = { 22 };
+static const int hgpio3_pins[] = { 23 };
+static const int hgpio4_pins[] = { 24 };
+static const int hgpio5_pins[] = { 25 };
+static const int hgpio6_pins[] = { 59 };
+static const int hgpio7_pins[] = { 60 };
+
/*
* pin: name, number
* group: name, npins, pins
@@ -631,6 +640,14 @@ struct npcm7xx_group {
NPCM7XX_GRP(lkgpo1), \
NPCM7XX_GRP(lkgpo2), \
NPCM7XX_GRP(nprd_smi), \
+ NPCM7XX_GRP(hgpio0), \
+ NPCM7XX_GRP(hgpio1), \
+ NPCM7XX_GRP(hgpio2), \
+ NPCM7XX_GRP(hgpio3), \
+ NPCM7XX_GRP(hgpio4), \
+ NPCM7XX_GRP(hgpio5), \
+ NPCM7XX_GRP(hgpio6), \
+ NPCM7XX_GRP(hgpio7), \
\
enum {
@@ -774,6 +791,14 @@ NPCM7XX_SFUNC(lkgpo0);
NPCM7XX_SFUNC(lkgpo1);
NPCM7XX_SFUNC(lkgpo2);
NPCM7XX_SFUNC(nprd_smi);
+NPCM7XX_SFUNC(hgpio0);
+NPCM7XX_SFUNC(hgpio1);
+NPCM7XX_SFUNC(hgpio2);
+NPCM7XX_SFUNC(hgpio3);
+NPCM7XX_SFUNC(hgpio4);
+NPCM7XX_SFUNC(hgpio5);
+NPCM7XX_SFUNC(hgpio6);
+NPCM7XX_SFUNC(hgpio7);
/* Function names */
static struct npcm7xx_func npcm7xx_funcs[] = {
@@ -892,6 +917,14 @@ static struct npcm7xx_func npcm7xx_funcs[] = {
NPCM7XX_MKFUNC(lkgpo1),
NPCM7XX_MKFUNC(lkgpo2),
NPCM7XX_MKFUNC(nprd_smi),
+ NPCM7XX_MKFUNC(hgpio0),
+ NPCM7XX_MKFUNC(hgpio1),
+ NPCM7XX_MKFUNC(hgpio2),
+ NPCM7XX_MKFUNC(hgpio3),
+ NPCM7XX_MKFUNC(hgpio4),
+ NPCM7XX_MKFUNC(hgpio5),
+ NPCM7XX_MKFUNC(hgpio6),
+ NPCM7XX_MKFUNC(hgpio7),
};
#define NPCM7XX_PINCFG(a, b, c, d, e, f, g, h, i, j, k) \
@@ -944,12 +977,12 @@ static const struct npcm7xx_pincfg pincfg[] = {
NPCM7XX_PINCFG(17, pspi2, MFSEL3, 13, smb4den, I2CSEGSEL, 23, none, NONE, 0, DS(8, 12)),
NPCM7XX_PINCFG(18, pspi2, MFSEL3, 13, smb4b, I2CSEGSEL, 14, none, NONE, 0, DS(8, 12)),
NPCM7XX_PINCFG(19, pspi2, MFSEL3, 13, smb4b, I2CSEGSEL, 14, none, NONE, 0, DS(8, 12)),
- NPCM7XX_PINCFG(20, smb4c, I2CSEGSEL, 15, smb15, MFSEL3, 8, none, NONE, 0, 0),
- NPCM7XX_PINCFG(21, smb4c, I2CSEGSEL, 15, smb15, MFSEL3, 8, none, NONE, 0, 0),
- NPCM7XX_PINCFG(22, smb4d, I2CSEGSEL, 16, smb14, MFSEL3, 7, none, NONE, 0, 0),
- NPCM7XX_PINCFG(23, smb4d, I2CSEGSEL, 16, smb14, MFSEL3, 7, none, NONE, 0, 0),
- NPCM7XX_PINCFG(24, ioxh, MFSEL3, 18, none, NONE, 0, none, NONE, 0, DS(8, 12)),
- NPCM7XX_PINCFG(25, ioxh, MFSEL3, 18, none, NONE, 0, none, NONE, 0, DS(8, 12)),
+ NPCM7XX_PINCFG(20, hgpio0, MFSEL2, 24, smb15, MFSEL3, 8, smb4c, I2CSEGSEL, 15, 0),
+ NPCM7XX_PINCFG(21, hgpio1, MFSEL2, 25, smb15, MFSEL3, 8, smb4c, I2CSEGSEL, 15, 0),
+ NPCM7XX_PINCFG(22, hgpio2, MFSEL2, 26, smb14, MFSEL3, 7, smb4d, I2CSEGSEL, 16, 0),
+ NPCM7XX_PINCFG(23, hgpio3, MFSEL2, 27, smb14, MFSEL3, 7, smb4d, I2CSEGSEL, 16, 0),
+ NPCM7XX_PINCFG(24, hgpio4, MFSEL2, 28, ioxh, MFSEL3, 18, none, NONE, 0, DS(8, 12)),
+ NPCM7XX_PINCFG(25, hgpio5, MFSEL2, 29, ioxh, MFSEL3, 18, none, NONE, 0, DS(8, 12)),
NPCM7XX_PINCFG(26, smb5, MFSEL1, 2, none, NONE, 0, none, NONE, 0, 0),
NPCM7XX_PINCFG(27, smb5, MFSEL1, 2, none, NONE, 0, none, NONE, 0, 0),
NPCM7XX_PINCFG(28, smb4, MFSEL1, 1, none, NONE, 0, none, NONE, 0, 0),
@@ -982,8 +1015,8 @@ static const struct npcm7xx_pincfg pincfg[] = {
NPCM7XX_PINCFG(56, r1err, MFSEL1, 12, none, NONE, 0, none, NONE, 0, 0),
NPCM7XX_PINCFG(57, r1md, MFSEL1, 13, none, NONE, 0, none, NONE, 0, DS(2, 4)),
NPCM7XX_PINCFG(58, r1md, MFSEL1, 13, none, NONE, 0, none, NONE, 0, DS(2, 4)),
- NPCM7XX_PINCFG(59, smb3d, I2CSEGSEL, 13, none, NONE, 0, none, NONE, 0, 0),
- NPCM7XX_PINCFG(60, smb3d, I2CSEGSEL, 13, none, NONE, 0, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(59, hgpio6, MFSEL2, 30, smb3d, I2CSEGSEL, 13, none, NONE, 0, 0),
+ NPCM7XX_PINCFG(60, hgpio7, MFSEL2, 31, smb3d, I2CSEGSEL, 13, none, NONE, 0, 0),
NPCM7XX_PINCFG(61, uart1, MFSEL1, 10, none, NONE, 0, none, NONE, 0, GPO),
NPCM7XX_PINCFG(62, uart1, MFSEL1, 10, bmcuart1, MFSEL3, 24, none, NONE, 0, GPO),
NPCM7XX_PINCFG(63, uart1, MFSEL1, 10, bmcuart1, MFSEL3, 24, none, NONE, 0, GPO),
@@ -1188,12 +1221,12 @@ static const struct pinctrl_pin_desc npcm7xx_pins[] = {
PINCTRL_PIN(17, "GPIO17/PSPI2DI/SMB4DEN"),
PINCTRL_PIN(18, "GPIO18/PSPI2D0/SMB4BSDA"),
PINCTRL_PIN(19, "GPIO19/PSPI2CK/SMB4BSCL"),
- PINCTRL_PIN(20, "GPIO20/SMB4CSDA/SMB15SDA"),
- PINCTRL_PIN(21, "GPIO21/SMB4CSCL/SMB15SCL"),
- PINCTRL_PIN(22, "GPIO22/SMB4DSDA/SMB14SDA"),
- PINCTRL_PIN(23, "GPIO23/SMB4DSCL/SMB14SCL"),
- PINCTRL_PIN(24, "GPIO24/IOXHDO"),
- PINCTRL_PIN(25, "GPIO25/IOXHDI"),
+ PINCTRL_PIN(20, "GPIO20/HGPIO0/SMB4CSDA/SMB15SDA"),
+ PINCTRL_PIN(21, "GPIO21/HGPIO1/SMB4CSCL/SMB15SCL"),
+ PINCTRL_PIN(22, "GPIO22/HGPIO2/SMB4DSDA/SMB14SDA"),
+ PINCTRL_PIN(23, "GPIO23/HGPIO3/SMB4DSCL/SMB14SCL"),
+ PINCTRL_PIN(24, "GPIO24/HGPIO4/IOXHDO"),
+ PINCTRL_PIN(25, "GPIO25/HGPIO5/IOXHDI"),
PINCTRL_PIN(26, "GPIO26/SMB5SDA"),
PINCTRL_PIN(27, "GPIO27/SMB5SCL"),
PINCTRL_PIN(28, "GPIO28/SMB4SDA"),
@@ -1226,8 +1259,8 @@ static const struct pinctrl_pin_desc npcm7xx_pins[] = {
PINCTRL_PIN(56, "GPIO56/R1RXERR"),
PINCTRL_PIN(57, "GPIO57/R1MDC"),
PINCTRL_PIN(58, "GPIO58/R1MDIO"),
- PINCTRL_PIN(59, "GPIO59/SMB3DSDA"),
- PINCTRL_PIN(60, "GPIO60/SMB3DSCL"),
+ PINCTRL_PIN(59, "GPIO59/HGPIO6/SMB3DSDA"),
+ PINCTRL_PIN(60, "GPIO60/HGPIO7/SMB3DSCL"),
PINCTRL_PIN(61, "GPO61/nDTR1_BOUT1/STRAP6"),
PINCTRL_PIN(62, "GPO62/nRTST1/STRAP5"),
PINCTRL_PIN(63, "GPO63/TXD1/STRAP4"),
--
2.22.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH linux dev-5.8 v2 07/11] pinctrl: pinconf: add pin persist configuration
2021-01-05 13:44 [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Tomer Maimon
` (5 preceding siblings ...)
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 06/11] pinctrl: npcm7xx: Add HGPIO pin support to NPCM7xx pinctrl driver Tomer Maimon
@ 2021-01-05 13:45 ` Tomer Maimon
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 08/11] pinctrl: npcm7xx: Add pin persist configuration support Tomer Maimon
` (4 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Tomer Maimon @ 2021-01-05 13:45 UTC (permalink / raw)
To: openbmc; +Cc: Andrew Jeffery, Tomer Maimon, benjaminfair
Add generic pin persist configuration support.
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
drivers/pinctrl/pinconf-generic.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index dfef471201f6..c609a69bd37e 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -50,6 +50,7 @@ static const struct pin_config_item conf_items[] = {
PCONFDUMP(PIN_CONFIG_SLEEP_HARDWARE_STATE, "sleep hardware state", NULL, false),
PCONFDUMP(PIN_CONFIG_SLEW_RATE, "slew rate", NULL, true),
PCONFDUMP(PIN_CONFIG_SKEW_DELAY, "skew delay", NULL, true),
+ PCONFDUMP(PIN_CONFIG_PERSIST_STATE, "persist state", NULL, false),
};
static void pinconf_generic_dump_one(struct pinctrl_dev *pctldev,
@@ -184,6 +185,8 @@ static const struct pinconf_generic_params dt_params[] = {
{ "sleep-hardware-state", PIN_CONFIG_SLEEP_HARDWARE_STATE, 0 },
{ "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
{ "skew-delay", PIN_CONFIG_SKEW_DELAY, 0 },
+ { "persist-state", PIN_CONFIG_PERSIST_STATE, 0 },
+ { "reset-state", PIN_CONFIG_PERSIST_STATE, 1 },
};
/**
--
2.22.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH linux dev-5.8 v2 08/11] pinctrl: npcm7xx: Add pin persist configuration support
2021-01-05 13:44 [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Tomer Maimon
` (6 preceding siblings ...)
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 07/11] pinctrl: pinconf: add pin persist configuration Tomer Maimon
@ 2021-01-05 13:45 ` Tomer Maimon
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 09/11] spi: npcm-pspi: Add full duplex support Tomer Maimon
` (3 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Tomer Maimon @ 2021-01-05 13:45 UTC (permalink / raw)
To: openbmc; +Cc: Andrew Jeffery, Tomer Maimon, benjaminfair
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c | 65 +++++++++++++++++++++++
1 file changed, 65 insertions(+)
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
index e5f58ea89917..ec12efd23bbe 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
@@ -36,6 +36,19 @@
#define SRCNT_ESPI BIT(3)
+/* reset registers */
+#define NPCM7XX_RST_WD0RCR 0x38
+#define NPCM7XX_RST_WD1RCR 0x3C
+#define NPCM7XX_RST_WD2RCR 0x40
+#define NPCM7XX_RST_SWRSTC1 0x44
+#define NPCM7XX_RST_SWRSTC2 0x48
+#define NPCM7XX_RST_SWRSTC3 0x4C
+#define NPCM7XX_RST_SWRSTC4 0x50
+#define NPCM7XX_RST_CORSTC 0x5C
+
+#define GPIOX_MODULE_RESET BIT(16)
+#define CA9C_MODULE_RESET BIT(0)
+
/* GPIO registers */
#define NPCM7XX_GP_N_TLOCK1 0x00
#define NPCM7XX_GP_N_DIN 0x04 /* Data IN */
@@ -94,6 +107,7 @@ struct npcm7xx_pinctrl {
struct npcm7xx_gpio gpio_bank[NPCM7XX_GPIO_BANK_NUM];
struct irq_domain *domain;
struct regmap *gcr_regmap;
+ struct regmap *rst_regmap;
void __iomem *regs;
u32 bank_num;
};
@@ -1583,6 +1597,48 @@ static int npcm7xx_set_drive_strength(struct npcm7xx_pinctrl *npcm,
return -ENOTSUPP;
}
+static int npcm7xx_gpio_reset_persist(struct npcm7xx_pinctrl *npcm,
+ unsigned int pin, int enable)
+{
+ struct npcm7xx_gpio *bank =
+ &npcm->gpio_bank[pin / NPCM7XX_GPIO_PER_BANK];
+ int banknum = pin / bank->gc.ngpio;
+
+ if (enable) {
+ regmap_update_bits(npcm->rst_regmap, NPCM7XX_RST_WD0RCR,
+ GPIOX_MODULE_RESET << banknum, 0);
+ regmap_update_bits(npcm->rst_regmap, NPCM7XX_RST_WD1RCR,
+ GPIOX_MODULE_RESET << banknum, 0);
+ regmap_update_bits(npcm->rst_regmap, NPCM7XX_RST_WD2RCR,
+ GPIOX_MODULE_RESET << banknum, 0);
+ regmap_update_bits(npcm->rst_regmap, NPCM7XX_RST_CORSTC,
+ GPIOX_MODULE_RESET << banknum, 0);
+ } else {
+ regmap_update_bits(npcm->rst_regmap, NPCM7XX_RST_WD0RCR,
+ (GPIOX_MODULE_RESET << banknum) |
+ CA9C_MODULE_RESET,
+ (GPIOX_MODULE_RESET << banknum) |
+ CA9C_MODULE_RESET);
+ regmap_update_bits(npcm->rst_regmap, NPCM7XX_RST_WD1RCR,
+ (GPIOX_MODULE_RESET << banknum) |
+ CA9C_MODULE_RESET,
+ (GPIOX_MODULE_RESET << banknum) |
+ CA9C_MODULE_RESET);
+ regmap_update_bits(npcm->rst_regmap, NPCM7XX_RST_WD2RCR,
+ (GPIOX_MODULE_RESET << banknum) |
+ CA9C_MODULE_RESET,
+ (GPIOX_MODULE_RESET << banknum) |
+ CA9C_MODULE_RESET);
+ regmap_update_bits(npcm->rst_regmap, NPCM7XX_RST_CORSTC,
+ (GPIOX_MODULE_RESET << banknum) |
+ CA9C_MODULE_RESET,
+ (GPIOX_MODULE_RESET << banknum) |
+ CA9C_MODULE_RESET);
+ }
+
+ return 0;
+}
+
/* pinctrl_ops */
static void npcm7xx_pin_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned int offset)
@@ -1852,6 +1908,8 @@ static int npcm7xx_config_set_one(struct npcm7xx_pinctrl *npcm,
return npcm7xx_set_slew_rate(bank, npcm->gcr_regmap, pin, arg);
case PIN_CONFIG_DRIVE_STRENGTH:
return npcm7xx_set_drive_strength(npcm, pin, arg);
+ case PIN_CONFIG_PERSIST_STATE:
+ return npcm7xx_gpio_reset_persist(npcm, pin, arg);
default:
return -ENOTSUPP;
}
@@ -2051,6 +2109,13 @@ static int npcm7xx_pinctrl_probe(struct platform_device *pdev)
return PTR_ERR(pctrl->gcr_regmap);
}
+ pctrl->rst_regmap =
+ syscon_regmap_lookup_by_compatible("nuvoton,npcm750-rst");
+ if (IS_ERR(pctrl->rst_regmap)) {
+ dev_err(pctrl->dev, "didn't find nuvoton,npcm750-rst\n");
+ return PTR_ERR(pctrl->rst_regmap);
+ }
+
ret = npcm7xx_gpio_of(pctrl);
if (ret < 0) {
dev_err(pctrl->dev, "Failed to gpio dt-binding %u\n", ret);
--
2.22.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH linux dev-5.8 v2 09/11] spi: npcm-pspi: Add full duplex support
2021-01-05 13:44 [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Tomer Maimon
` (7 preceding siblings ...)
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 08/11] pinctrl: npcm7xx: Add pin persist configuration support Tomer Maimon
@ 2021-01-05 13:45 ` Tomer Maimon
2021-01-11 1:04 ` Joel Stanley
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 10/11] dt-binding: bmc: add NPCM7XX JTAG master documentation Tomer Maimon
` (2 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: Tomer Maimon @ 2021-01-05 13:45 UTC (permalink / raw)
To: openbmc; +Cc: Andrew Jeffery, Tomer Maimon, benjaminfair
Modify the IRQ handler in the NPCM PSPI
driver to support SPI full duplex communication.
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
drivers/spi/spi-npcm-pspi.c | 75 +++++++++++++++----------------------
1 file changed, 30 insertions(+), 45 deletions(-)
diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c
index 87cd0233c60b..92fae0b23eb1 100644
--- a/drivers/spi/spi-npcm-pspi.c
+++ b/drivers/spi/spi-npcm-pspi.c
@@ -197,22 +197,22 @@ static void npcm_pspi_setup_transfer(struct spi_device *spi,
static void npcm_pspi_send(struct npcm_pspi *priv)
{
int wsize;
- u16 val;
+ u16 val = 0;
wsize = min(bytes_per_word(priv->bits_per_word), priv->tx_bytes);
priv->tx_bytes -= wsize;
- if (!priv->tx_buf)
- return;
-
switch (wsize) {
case 1:
- val = *priv->tx_buf++;
+ if (priv->tx_buf)
+ val = *priv->tx_buf++;
iowrite8(val, NPCM_PSPI_DATA + priv->base);
break;
case 2:
- val = *priv->tx_buf++;
- val = *priv->tx_buf++ | (val << 8);
+ if (priv->tx_buf) {
+ val = *priv->tx_buf++;
+ val = *priv->tx_buf++ | (val << 8);
+ }
iowrite16(val, NPCM_PSPI_DATA + priv->base);
break;
default:
@@ -224,22 +224,24 @@ static void npcm_pspi_send(struct npcm_pspi *priv)
static void npcm_pspi_recv(struct npcm_pspi *priv)
{
int rsize;
- u16 val;
+ u16 val_16;
+ u8 val_8;
rsize = min(bytes_per_word(priv->bits_per_word), priv->rx_bytes);
priv->rx_bytes -= rsize;
- if (!priv->rx_buf)
- return;
-
switch (rsize) {
case 1:
- *priv->rx_buf++ = ioread8(priv->base + NPCM_PSPI_DATA);
+ val_8 = ioread8(priv->base + NPCM_PSPI_DATA);
+ if (priv->rx_buf)
+ *priv->rx_buf++ = val_8;
break;
case 2:
- val = ioread16(priv->base + NPCM_PSPI_DATA);
- *priv->rx_buf++ = (val >> 8);
- *priv->rx_buf++ = val & 0xff;
+ val_16 = ioread16(priv->base + NPCM_PSPI_DATA);
+ if (priv->rx_buf) {
+ *priv->rx_buf++ = (val_16 >> 8);
+ *priv->rx_buf++ = val_16 & 0xff;
+ }
break;
default:
WARN_ON_ONCE(1);
@@ -298,43 +300,26 @@ static irqreturn_t npcm_pspi_handler(int irq, void *dev_id)
struct npcm_pspi *priv = dev_id;
u8 stat;
- stat = ioread8(priv->base + NPCM_PSPI_STAT);
-
if (!priv->tx_buf && !priv->rx_buf)
return IRQ_NONE;
- if (priv->tx_buf) {
- if (stat & NPCM_PSPI_STAT_RBF) {
- ioread8(NPCM_PSPI_DATA + priv->base);
- if (priv->tx_bytes == 0) {
- npcm_pspi_disable(priv);
- complete(&priv->xfer_done);
- return IRQ_HANDLED;
- }
- }
-
- if ((stat & NPCM_PSPI_STAT_BSY) == 0)
- if (priv->tx_bytes)
- npcm_pspi_send(priv);
+ if (priv->tx_bytes == 0 && priv->rx_bytes == 0) {
+ npcm_pspi_disable(priv);
+ complete(&priv->xfer_done);
+ return IRQ_HANDLED;
}
- if (priv->rx_buf) {
- if (stat & NPCM_PSPI_STAT_RBF) {
- if (!priv->rx_bytes)
- return IRQ_NONE;
-
- npcm_pspi_recv(priv);
+ stat = ioread8(priv->base + NPCM_PSPI_STAT);
- if (!priv->rx_bytes) {
- npcm_pspi_disable(priv);
- complete(&priv->xfer_done);
- return IRQ_HANDLED;
- }
- }
+ /*
+ * first we do the read since if we do the write we previous read might
+ * be lost (indeed low chances)
+ */
+ if ((stat & NPCM_PSPI_STAT_RBF) && priv->rx_bytes)
+ npcm_pspi_recv(priv);
- if (((stat & NPCM_PSPI_STAT_BSY) == 0) && !priv->tx_buf)
- iowrite8(0x0, NPCM_PSPI_DATA + priv->base);
- }
+ if (((stat & NPCM_PSPI_STAT_BSY) == 0) && priv->tx_bytes)
+ npcm_pspi_send(priv);
return IRQ_HANDLED;
}
--
2.22.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH linux dev-5.8 v2 10/11] dt-binding: bmc: add NPCM7XX JTAG master documentation
2021-01-05 13:44 [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Tomer Maimon
` (8 preceding siblings ...)
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 09/11] spi: npcm-pspi: Add full duplex support Tomer Maimon
@ 2021-01-05 13:45 ` Tomer Maimon
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 11/11] misc: npcm7xx-jtag-master: add NPCM7xx JTAG master driver Tomer Maimon
2021-01-11 0:37 ` [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Joel Stanley
11 siblings, 0 replies; 20+ messages in thread
From: Tomer Maimon @ 2021-01-05 13:45 UTC (permalink / raw)
To: openbmc; +Cc: Andrew Jeffery, Stanley Chu, Tomer Maimon, benjaminfair
Added device tree binding documentation for
Nuvoton NPCM7XX JTAG master.
Signed-off-by: Stanley Chu <yschu@nuvoton.com>
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
.../bindings/bmc/npcm7xx-jtag-master.txt | 38 +++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 Documentation/devicetree/bindings/bmc/npcm7xx-jtag-master.txt
diff --git a/Documentation/devicetree/bindings/bmc/npcm7xx-jtag-master.txt b/Documentation/devicetree/bindings/bmc/npcm7xx-jtag-master.txt
new file mode 100644
index 000000000000..3ad7a18ba9a2
--- /dev/null
+++ b/Documentation/devicetree/bindings/bmc/npcm7xx-jtag-master.txt
@@ -0,0 +1,38 @@
+Nuvoton NPCM7xx JTAG MASTER interface
+
+Nuvoton BMC NPCM7xx JTAG Master is used for debugging host CPU or programming
+CPLD device. The driver is implemented as an SPI device driver that enabling
+the option to transfer JTAG data with the assistance of SPI HW.
+
+Required properties for jtag_master node
+- compatible : "nuvoton,npcm750-jtag-master" for Poleg NPCM7XX.
+- spi-max-frequency : specify the max spi bus frequency.
+- reg : always 0
+- pinctrl-names : contain 2 pinctrl states "pspi" and "gpio", which indicates
+ the TCK/TDI/TDO pin state in HW mode(using PSPI hw) and
+ SW mode (using GPIO bitbang) respectively.
+- tck-gpios : specify the GPIO number of TCK pin
+- tdi-gpios : specify the GPIO number of TDI pin
+- tdo-gpios : specify the GPIO number of TDO pin
+- tms-gpios : specify the GPIO number of TMS pin
+
+Example:
+spi1: spi@201000 {
+ ...
+ jtag_master {
+ compatible = "nuvoton,npcm750-jtag-master";
+ spi-max-frequency = <25000000>;
+ reg = <0>;
+
+ pinctrl-names = "pspi", "gpio";
+ pinctrl-0 = <&pspi2_pins>;
+ pinctrl-1 = <&gpio17_pins &gpio18o_pins
+ &gpio19ol_pins>;
+
+ tck-gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>;
+ tdi-gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>;
+ tdo-gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+ tms-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+ };
+};
--
2.22.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH linux dev-5.8 v2 11/11] misc: npcm7xx-jtag-master: add NPCM7xx JTAG master driver
2021-01-05 13:44 [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Tomer Maimon
` (9 preceding siblings ...)
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 10/11] dt-binding: bmc: add NPCM7XX JTAG master documentation Tomer Maimon
@ 2021-01-05 13:45 ` Tomer Maimon
2021-01-11 0:37 ` [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Joel Stanley
11 siblings, 0 replies; 20+ messages in thread
From: Tomer Maimon @ 2021-01-05 13:45 UTC (permalink / raw)
To: openbmc; +Cc: Andrew Jeffery, Stanley Chu, Tomer Maimon, benjaminfair
Add NPCM7xx JTAG master driver,
The NPCM7xx JTAG master usign GPIO lines
and NPCM PSPI bus.
Signed-off-by: Stanley Chu <yschu@nuvoton.com>
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
drivers/misc/Kconfig | 6 +
drivers/misc/Makefile | 1 +
drivers/misc/npcm7xx-jtag-master.c | 840 +++++++++++++++++++++++++++++
3 files changed, 847 insertions(+)
create mode 100644 drivers/misc/npcm7xx-jtag-master.c
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index d8626a0d3e31..1b1876284fa6 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -478,6 +478,12 @@ config NPCM7XX_PCI_MBOX
Expose the NPCM750/730/715/705 PCI MBOX registers found on
Nuvoton SOCs to userspace.
+config NPCM7XX_JTAG_MASTER
+ tristate "NPCM7xx JTAG Master driver"
+ depends on (ARCH_NPCM7XX || COMPILE_TEST)
+ help
+ Control PSPI/GPIO to transmit jtag signals to support jtag master function.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 183970192ced..b11d3c21fa03 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -59,4 +59,5 @@ obj-$(CONFIG_UACCE) += uacce/
obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o
obj-$(CONFIG_NPCM7XX_LPC_BPC) += npcm7xx-lpc-bpc.o
obj-$(CONFIG_NPCM7XX_PCI_MBOX) += npcm7xx-pci-mbox.o
+obj-$(CONFIG_NPCM7XX_JTAG_MASTER) += npcm7xx-jtag-master.o
obj-$(CONFIG_MCTP_LPC) += mctp-lpc.o
diff --git a/drivers/misc/npcm7xx-jtag-master.c b/drivers/misc/npcm7xx-jtag-master.c
new file mode 100644
index 000000000000..4d254cc0e159
--- /dev/null
+++ b/drivers/misc/npcm7xx-jtag-master.c
@@ -0,0 +1,840 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Description : JTAG Master driver
+ *
+ * Copyright (C) 2019 NuvoTon Corporation
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/spi/spi.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/gpio/consumer.h>
+
+#define JTAG_PSPI_SPEED (10 * 1000000)
+#define JTAG_SCAN_LEN 256
+#define JTAG_MAX_XFER_DATA_LEN 65535
+
+struct tck_bitbang {
+ unsigned char tms;
+ unsigned char tdi; /* TDI bit value to write */
+ unsigned char tdo; /* TDO bit value to read */
+};
+
+struct bitbang_packet {
+ struct tck_bitbang *data;
+ __u32 length;
+} __attribute__((__packed__));
+
+struct scan_xfer {
+ unsigned int length; /* number of bits */
+ unsigned char tdi[JTAG_SCAN_LEN];
+ unsigned int tdi_bytes;
+ unsigned char tdo[JTAG_SCAN_LEN];
+ unsigned int tdo_bytes;
+ unsigned int end_tap_state;
+};
+
+struct jtag_xfer {
+ __u8 type;
+ __u8 direction;
+ __u8 from;
+ __u8 endstate;
+ __u32 padding;
+ __u32 length;
+ __u64 tdio;
+};
+
+struct jtag_tap_state {
+ __u8 reset;
+ __u8 from;
+ __u8 endstate;
+ __u8 tck;
+};
+
+enum jtagstates {
+ jtagtlr,
+ jtagrti,
+ jtagseldr,
+ jtagcapdr,
+ jtagshfdr,
+ jtagex1dr,
+ jtagpaudr,
+ jtagex2dr,
+ jtagupddr,
+ jtagselir,
+ jtagcapir,
+ jtagshfir,
+ jtagex1ir,
+ jtagpauir,
+ jtagex2ir,
+ jtagupdir,
+ JTAG_STATE_CURRENT
+};
+
+enum JTAG_PIN {
+ pin_TCK,
+ pin_TDI,
+ pin_TDO,
+ pin_TMS,
+ pin_NUM,
+};
+
+enum jtag_reset {
+ JTAG_NO_RESET = 0,
+ JTAG_FORCE_RESET = 1,
+};
+
+enum jtag_xfer_type {
+ JTAG_SIR_XFER = 0,
+ JTAG_SDR_XFER = 1,
+ JTAG_RUNTEST_XFER,
+};
+
+enum jtag_xfer_direction {
+ JTAG_READ_XFER = 1,
+ JTAG_WRITE_XFER = 2,
+ JTAG_READ_WRITE_XFER = 3,
+};
+
+#define __JTAG_IOCTL_MAGIC 0xb2
+#define JTAG_SIOCSTATE _IOW(__JTAG_IOCTL_MAGIC, 0, struct jtag_tap_state)
+#define JTAG_SIOCFREQ _IOW(__JTAG_IOCTL_MAGIC, 1, unsigned int)
+#define JTAG_GIOCFREQ _IOR(__JTAG_IOCTL_MAGIC, 2, unsigned int)
+#define JTAG_IOCXFER _IOWR(__JTAG_IOCTL_MAGIC, 3, struct jtag_xfer)
+#define JTAG_GIOCSTATUS _IOWR(__JTAG_IOCTL_MAGIC, 4, enum jtagstates)
+#define JTAG_SIOCMODE _IOW(__JTAG_IOCTL_MAGIC, 5, unsigned int)
+#define JTAG_IOCBITBANG _IOW(__JTAG_IOCTL_MAGIC, 6, unsigned int)
+#define JTAG_RUNTEST _IOW(__JTAG_IOCTL_MAGIC, 7, unsigned int)
+
+static DEFINE_IDA(jtag_ida);
+
+static unsigned char reverse[16] = {
+ 0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
+ 0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF
+};
+
+#define REVERSE(x) ((reverse[((x) & 0x0f)] << 4) | reverse[((x) & 0xf0) >> 4])
+
+static DEFINE_SPINLOCK(jtag_file_lock);
+
+struct jtag_info {
+ struct device *dev;
+ struct spi_device *spi;
+ struct miscdevice miscdev;
+ struct gpio_desc *pins[pin_NUM];
+ struct pinctrl *pinctrl;
+ u32 freq;
+ u8 tms_level;
+ u8 tapstate;
+ bool is_open;
+ int id;
+
+ /* transmit tck/tdi/tdo by pspi */
+ #define MODE_PSPI 0
+ /* transmit all signals by gpio */
+ #define MODE_GPIO 1
+ u8 mode;
+};
+
+/* 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 tmscycle {
+ 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
+ */
+const struct tmscycle _tmscyclelookup[][16] = {
+/* TLR RTI SelDR CapDR SDR */
+/* Ex1DR PDR Ex2DR UpdDR SelIR */
+/* CapIR SIR Ex1IR PIR Ex2IR */
+/* UpdIR */
+/* TLR */
+ {
+ {0x01, 1}, {0x00, 1}, {0x02, 2}, {0x02, 3}, {0x02, 4},
+ {0x0a, 4}, {0x0a, 5}, {0x2a, 6}, {0x1a, 5}, {0x06, 3},
+ {0x06, 4}, {0x06, 5}, {0x16, 5}, {0x16, 6}, {0x56, 7},
+ {0x36, 6}
+ },
+/* RTI */
+ {
+ {0x07, 3}, {0x00, 1}, {0x01, 1}, {0x01, 2}, {0x01, 3},
+ {0x05, 3}, {0x05, 4}, {0x15, 5}, {0x0d, 4}, {0x03, 2},
+ {0x03, 3}, {0x03, 4}, {0x0b, 4}, {0x0b, 5}, {0x2b, 6},
+ {0x1b, 5}
+ },
+/* SelDR */
+ {
+ {0x03, 2}, {0x03, 3}, {0x00, 0}, {0x00, 1}, {0x00, 2},
+ {0x02, 2}, {0x02, 3}, {0x0a, 4}, {0x06, 3}, {0x01, 1},
+ {0x01, 2}, {0x01, 3}, {0x05, 3}, {0x05, 4}, {0x15, 5},
+ {0x0d, 4}
+ },
+/* CapDR */
+ {
+ {0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x00, 0}, {0x00, 1},
+ {0x01, 1}, {0x01, 2}, {0x05, 3}, {0x03, 2}, {0x0f, 4},
+ {0x0f, 5}, {0x0f, 6}, {0x2f, 6}, {0x2f, 7}, {0xaf, 8},
+ {0x6f, 7}
+ },
+/* SDR */
+ {
+ {0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x00, 0},
+ {0x01, 1}, {0x01, 2}, {0x05, 3}, {0x03, 2}, {0x0f, 4},
+ {0x0f, 5}, {0x0f, 6}, {0x2f, 6}, {0x2f, 7}, {0xaf, 8},
+ {0x6f, 7}
+ },
+/* Ex1DR */
+ {
+ {0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x02, 3},
+ {0x00, 0}, {0x00, 1}, {0x02, 2}, {0x01, 1}, {0x07, 3},
+ {0x07, 4}, {0x07, 5}, {0x17, 5}, {0x17, 6}, {0x57, 7},
+ {0x37, 6}
+ },
+/* PDR */
+ {
+ {0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x01, 2},
+ {0x05, 3}, {0x00, 1}, {0x01, 1}, {0x03, 2}, {0x0f, 4},
+ {0x0f, 5}, {0x0f, 6}, {0x2f, 6}, {0x2f, 7}, {0xaf, 8},
+ {0x6f, 7}
+ },
+/* Ex2DR */
+ {
+ {0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x00, 1},
+ {0x02, 2}, {0x02, 3}, {0x00, 0}, {0x01, 1}, {0x07, 3},
+ {0x07, 4}, {0x07, 5}, {0x17, 5}, {0x17, 6}, {0x57, 7},
+ {0x37, 6}
+ },
+/* UpdDR */
+ {
+ {0x07, 3}, {0x00, 1}, {0x01, 1}, {0x01, 2}, {0x01, 3},
+ {0x05, 3}, {0x05, 4}, {0x15, 5}, {0x00, 0}, {0x03, 2},
+ {0x03, 3}, {0x03, 4}, {0x0b, 4}, {0x0b, 5}, {0x2b, 6},
+ {0x1b, 5}
+ },
+/* SelIR */
+ {
+ {0x01, 1}, {0x01, 2}, {0x05, 3}, {0x05, 4}, {0x05, 5},
+ {0x15, 5}, {0x15, 6}, {0x55, 7}, {0x35, 6}, {0x00, 0},
+ {0x00, 1}, {0x00, 2}, {0x02, 2}, {0x02, 3}, {0x0a, 4},
+ {0x06, 3}
+ },
+/* CapIR */
+ {
+ {0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x07, 5},
+ {0x17, 5}, {0x17, 6}, {0x57, 7}, {0x37, 6}, {0x0f, 4},
+ {0x00, 0}, {0x00, 1}, {0x01, 1}, {0x01, 2}, {0x05, 3},
+ {0x03, 2}
+ },
+/* SIR */
+ {
+ {0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x07, 5},
+ {0x17, 5}, {0x17, 6}, {0x57, 7}, {0x37, 6}, {0x0f, 4},
+ {0x0f, 5}, {0x00, 0}, {0x01, 1}, {0x01, 2}, {0x05, 3},
+ {0x03, 2}
+ },
+/* Ex1IR */
+ {
+ {0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x03, 4},
+ {0x0b, 4}, {0x0b, 5}, {0x2b, 6}, {0x1b, 5}, {0x07, 3},
+ {0x07, 4}, {0x02, 3}, {0x00, 0}, {0x00, 1}, {0x02, 2},
+ {0x01, 1}
+ },
+/* PIR */
+ {
+ {0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x07, 5},
+ {0x17, 5}, {0x17, 6}, {0x57, 7}, {0x37, 6}, {0x0f, 4},
+ {0x0f, 5}, {0x01, 2}, {0x05, 3}, {0x00, 1}, {0x01, 1},
+ {0x03, 2}
+ },
+/* Ex2IR */
+ {
+ {0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x03, 4},
+ {0x0b, 4}, {0x0b, 5}, {0x2b, 6}, {0x1b, 5}, {0x07, 3},
+ {0x07, 4}, {0x00, 1}, {0x02, 2}, {0x02, 3}, {0x00, 0},
+ {0x01, 1}
+ },
+/* UpdIR */
+ {
+ {0x07, 3}, {0x00, 1}, {0x01, 1}, {0x01, 2}, {0x01, 3},
+ {0x05, 3}, {0x05, 4}, {0x15, 5}, {0x0d, 4}, {0x03, 2},
+ {0x03, 3}, {0x03, 4}, {0x0b, 4}, {0x0b, 5}, {0x2b, 6},
+ {0x00, 0}
+ },
+};
+
+static u8 TCK_cycle(struct jtag_info *jtag,
+ unsigned char no_tdo, unsigned char TMS,
+ unsigned char TDI)
+{
+ u32 tdo = 0;
+
+ /* IEEE 1149.1
+ * TMS & TDI shall be sampled by the test logic on the rising edge
+ * test logic shall change TDO on the falling edge
+ */
+ gpiod_set_value(jtag->pins[pin_TDI], (int)TDI);
+ if (jtag->tms_level != (int)TMS) {
+ gpiod_set_value(jtag->pins[pin_TMS], (int)TMS);
+ jtag->tms_level = (int)TMS;
+ }
+ gpiod_set_value(jtag->pins[pin_TCK], 1);
+ if (!no_tdo)
+ tdo = gpiod_get_value(jtag->pins[pin_TDO]);
+ gpiod_set_value(jtag->pins[pin_TCK], 0);
+
+ return tdo;
+}
+
+static inline void npcm7xx_jtag_bitbangs(struct jtag_info *jtag,
+ struct bitbang_packet *bitbangs,
+ struct tck_bitbang *bitbang_data)
+{
+ int i;
+
+ for (i = 0; i < bitbangs->length; i++) {
+ bitbang_data[i].tdo =
+ TCK_cycle(jtag, 0, bitbang_data[i].tms,
+ bitbang_data[i].tdi);
+ cond_resched();
+ }
+}
+
+static int npcm7xx_jtag_set_tapstate(struct jtag_info *jtag,
+ enum jtagstates from, enum jtagstates to)
+{
+ unsigned char i;
+ unsigned char tmsbits;
+ unsigned char count;
+
+ if (from == to)
+ return 0;
+ if (from == JTAG_STATE_CURRENT)
+ from = jtag->tapstate;
+
+ if (from > JTAG_STATE_CURRENT || to > JTAG_STATE_CURRENT)
+ return -1;
+
+ if (to == jtagtlr) {
+ for (i = 0; i < 9; i++)
+ TCK_cycle(jtag, 1, 1, 1);
+ jtag->tapstate = jtagtlr;
+ return 0;
+ }
+
+ tmsbits = _tmscyclelookup[from][to].tmsbits;
+ count = _tmscyclelookup[from][to].count;
+
+ if (count == 0)
+ return 0;
+
+ for (i = 0; i < count; i++) {
+ TCK_cycle(jtag, 1, (tmsbits & 1), 1);
+ tmsbits >>= 1;
+ }
+ pr_debug("jtag: change state %d -> %d\n", from, to);
+ jtag->tapstate = to;
+ return 0;
+}
+
+static int npcm7xx_jtag_switch_pin_func(struct jtag_info *jtag, u8 mode)
+{
+ struct pinctrl_state *state;
+
+ if (mode == MODE_PSPI) {
+ state = pinctrl_lookup_state(jtag->pinctrl, "pspi");
+ if (IS_ERR(state))
+ return -ENOENT;
+
+ pinctrl_gpio_free(desc_to_gpio(jtag->pins[pin_TCK]));
+ pinctrl_gpio_free(desc_to_gpio(jtag->pins[pin_TDI]));
+ pinctrl_gpio_free(desc_to_gpio(jtag->pins[pin_TDO]));
+ pinctrl_select_state(jtag->pinctrl, state);
+ } else if (mode == MODE_GPIO) {
+ state = pinctrl_lookup_state(jtag->pinctrl, "gpio");
+ if (IS_ERR(state))
+ return -ENOENT;
+
+ pinctrl_select_state(jtag->pinctrl, state);
+ pinctrl_gpio_request(desc_to_gpio(jtag->pins[pin_TCK]));
+ pinctrl_gpio_request(desc_to_gpio(jtag->pins[pin_TDI]));
+ pinctrl_gpio_request(desc_to_gpio(jtag->pins[pin_TDO]));
+ jtag->tms_level = gpiod_get_value(jtag->pins[pin_TMS]);
+ }
+
+ return 0;
+}
+
+static int npcm7xx_jtag_xfer_spi(struct jtag_info *jtag, u32 xfer_bytes,
+ u8 *out, u8 *in)
+{
+ struct spi_message m;
+ struct spi_transfer spi_xfer;
+ int err;
+ int i;
+
+ err = npcm7xx_jtag_switch_pin_func(jtag, MODE_PSPI);
+ if (err)
+ return err;
+
+ for (i = 0; i < xfer_bytes; i++)
+ out[i] = REVERSE(out[i]);
+
+ memset(&spi_xfer, 0, sizeof(spi_xfer));
+ spi_xfer.speed_hz = jtag->freq;
+ spi_xfer.tx_buf = out;
+ spi_xfer.rx_buf = in;
+ spi_xfer.len = xfer_bytes;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&spi_xfer, &m);
+ err = spi_sync(jtag->spi, &m);
+
+ for (i = 0; i < xfer_bytes; i++)
+ in[i] = REVERSE(in[i]);
+
+ err = npcm7xx_jtag_switch_pin_func(jtag, MODE_GPIO);
+
+ return err;
+}
+
+static int npcm7xx_jtag_xfer_gpio(struct jtag_info *jtag,
+ struct jtag_xfer *xfer, u8 *out, u8 *in)
+{
+ unsigned long *bitmap_tdi = (unsigned long *)out;
+ unsigned long *bitmap_tdo = (unsigned long *)in;
+ u32 xfer_bits = xfer->length;
+ u32 bit_index = 0;
+ u8 tdi, tdo, tms;
+
+ while (bit_index < xfer_bits) {
+ tdi = 0;
+ tms = 0;
+
+ if (test_bit(bit_index, bitmap_tdi))
+ tdi = 1;
+
+ /* If this is the last bit, leave TMS high */
+ if ((bit_index == xfer_bits - 1) && xfer->endstate != jtagshfdr &&
+ xfer->endstate != jtagshfir && xfer->endstate != JTAG_STATE_CURRENT)
+ tms = 1;
+
+ /* shift 1 bit */
+ tdo = TCK_cycle(jtag, 0, tms, tdi);
+ cond_resched();
+ /* If it was the last bit in the scan and the end_tap_state is
+ * something other than shiftDR or shiftIR then go to Exit1.
+ * IMPORTANT Note: if the end_tap_state is ShiftIR/DR and the
+ * next call to this function is a shiftDR/IR then the driver
+ * will not change state!
+ */
+ if (tms)
+ jtag->tapstate = (jtag->tapstate == jtagshfdr) ?
+ jtagex1dr : jtagex1ir;
+
+ if (tdo)
+ bitmap_set(bitmap_tdo, bit_index, 1);
+
+ bit_index++;
+ }
+
+ return 0;
+}
+
+static int npcm7xx_jtag_readwrite_scan(struct jtag_info *jtag,
+ struct jtag_xfer *xfer, u8 *tdi, u8 *tdo)
+{
+ u32 xfer_bytes = DIV_ROUND_UP(xfer->length, BITS_PER_BYTE);
+ u32 remain_bits = xfer->length;
+ u32 spi_xfer_bytes = 0;
+
+ if (xfer_bytes > 1 && jtag->mode == MODE_PSPI) {
+ /* The last byte should be sent using gpio bitbang
+ * (TMS needed)
+ */
+ spi_xfer_bytes = xfer_bytes - 1;
+ if (npcm7xx_jtag_xfer_spi(jtag, spi_xfer_bytes, tdi, tdo))
+ return -EIO;
+ remain_bits -= spi_xfer_bytes * 8;
+ }
+
+ if (remain_bits) {
+ xfer->length = remain_bits;
+ npcm7xx_jtag_xfer_gpio(jtag, xfer, tdi + spi_xfer_bytes,
+ tdo + spi_xfer_bytes);
+ }
+
+ npcm7xx_jtag_set_tapstate(jtag, JTAG_STATE_CURRENT, xfer->endstate);
+
+ return 0;
+}
+
+static int npcm7xx_jtag_xfer(struct jtag_info *npcm7xx_jtag,
+ struct jtag_xfer *xfer, u8 *data, u32 bytes)
+{
+ u8 *tdo;
+ int ret;
+
+ if (xfer->length == 0)
+ return 0;
+
+ tdo = kzalloc(bytes, GFP_KERNEL);
+ if (!tdo)
+ return -ENOMEM;
+
+ if (xfer->type == JTAG_SIR_XFER)
+ npcm7xx_jtag_set_tapstate(npcm7xx_jtag, xfer->from, jtagshfir);
+ else if (xfer->type == JTAG_SDR_XFER)
+ npcm7xx_jtag_set_tapstate(npcm7xx_jtag, xfer->from, jtagshfdr);
+
+ ret = npcm7xx_jtag_readwrite_scan(npcm7xx_jtag, xfer, data, tdo);
+ memcpy(data, tdo, bytes);
+ kfree(tdo);
+
+ return ret;
+}
+
+/* Run in current state for specific number of tcks */
+static int npcm7xx_jtag_runtest(struct jtag_info *jtag, unsigned int tcks)
+{
+ struct jtag_xfer xfer;
+ u32 bytes = DIV_ROUND_UP(tcks, BITS_PER_BYTE);
+ u8 *buf;
+ u32 i;
+ int err;
+
+ if (jtag->mode != MODE_PSPI) {
+ for (i = 0; i < tcks; i++) {
+ TCK_cycle(jtag, 0, 0, 1);
+ cond_resched();
+ }
+ return 0;
+ }
+
+ buf = kzalloc(bytes, GFP_KERNEL);
+ xfer.type = JTAG_RUNTEST_XFER;
+ xfer.direction = JTAG_WRITE_XFER;
+ xfer.from = JTAG_STATE_CURRENT;
+ xfer.endstate = JTAG_STATE_CURRENT;
+ xfer.length = tcks;
+
+ err = npcm7xx_jtag_xfer(jtag, &xfer, buf, bytes);
+ kfree(buf);
+
+ return err;
+}
+
+static long jtag_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct jtag_info *priv = file->private_data;
+ struct jtag_tap_state tapstate;
+ void __user *argp = (void __user *)arg;
+ struct jtag_xfer xfer;
+ struct bitbang_packet bitbang;
+ struct tck_bitbang *bitbang_data;
+ u8 *xfer_data;
+ u32 data_size;
+ u32 value;
+ int ret = 0;
+
+ switch (cmd) {
+ case JTAG_SIOCFREQ:
+ if (get_user(value, (__u32 __user *)arg))
+ return -EFAULT;
+ if (value <= priv->spi->max_speed_hz) {
+ priv->freq = value;
+ } else {
+ dev_err(priv->dev, "%s: invalid jtag freq %u\n",
+ __func__, value);
+ ret = -EINVAL;
+ }
+ break;
+ case JTAG_GIOCFREQ:
+ if (put_user(priv->freq, (__u32 __user *)arg))
+ return -EFAULT;
+ break;
+ case JTAG_IOCBITBANG:
+ if (copy_from_user(&bitbang, (const void __user *)arg,
+ sizeof(struct bitbang_packet)))
+ return -EFAULT;
+
+ if (bitbang.length >= JTAG_MAX_XFER_DATA_LEN)
+ return -EINVAL;
+
+ data_size = bitbang.length * sizeof(struct tck_bitbang);
+ bitbang_data = memdup_user((void __user *)bitbang.data,
+ data_size);
+ if (IS_ERR(bitbang_data))
+ return -EFAULT;
+
+ npcm7xx_jtag_bitbangs(priv, &bitbang, bitbang_data);
+ ret = copy_to_user((void __user *)bitbang.data,
+ (void *)bitbang_data, data_size);
+ kfree(bitbang_data);
+ if (ret)
+ return -EFAULT;
+ break;
+ case JTAG_SIOCSTATE:
+ if (copy_from_user(&tapstate, (const void __user *)arg,
+ sizeof(struct jtag_tap_state)))
+ return -EFAULT;
+
+ if (tapstate.from > JTAG_STATE_CURRENT)
+ return -EINVAL;
+
+ if (tapstate.endstate > JTAG_STATE_CURRENT)
+ return -EINVAL;
+
+ if (tapstate.reset > JTAG_FORCE_RESET)
+ return -EINVAL;
+ if (tapstate.reset == JTAG_FORCE_RESET)
+ npcm7xx_jtag_set_tapstate(priv, JTAG_STATE_CURRENT,
+ jtagtlr);
+ npcm7xx_jtag_set_tapstate(priv, tapstate.from,
+ tapstate.endstate);
+ break;
+ case JTAG_GIOCSTATUS:
+ ret = put_user(priv->tapstate, (__u32 __user *)arg);
+ break;
+ case JTAG_IOCXFER:
+ if (copy_from_user(&xfer, argp, sizeof(struct jtag_xfer)))
+ return -EFAULT;
+
+ if (xfer.length >= JTAG_MAX_XFER_DATA_LEN)
+ return -EINVAL;
+
+ if (xfer.type > JTAG_SDR_XFER)
+ return -EINVAL;
+
+ if (xfer.direction > JTAG_READ_WRITE_XFER)
+ return -EINVAL;
+
+ if (xfer.from > JTAG_STATE_CURRENT)
+ return -EINVAL;
+
+ if (xfer.endstate > JTAG_STATE_CURRENT)
+ return -EINVAL;
+
+ data_size = DIV_ROUND_UP(xfer.length, BITS_PER_BYTE);
+ xfer_data = memdup_user(u64_to_user_ptr(xfer.tdio), data_size);
+ if (IS_ERR(xfer_data))
+ return -EFAULT;
+ ret = npcm7xx_jtag_xfer(priv, &xfer, xfer_data, data_size);
+ if (ret) {
+ kfree(xfer_data);
+ return -EIO;
+ }
+ ret = copy_to_user(u64_to_user_ptr(xfer.tdio),
+ (void *)xfer_data, data_size);
+ kfree(xfer_data);
+ if (ret)
+ return -EFAULT;
+
+ if (copy_to_user((void __user *)arg, (void *)&xfer,
+ sizeof(struct jtag_xfer)))
+ return -EFAULT;
+ break;
+ case JTAG_SIOCMODE:
+ if (get_user(value, (__u32 __user *)arg))
+ return -EFAULT;
+ if (value != MODE_GPIO && value != MODE_PSPI)
+ return -EINVAL;
+ priv->mode = value;
+ break;
+ case JTAG_RUNTEST:
+ ret = npcm7xx_jtag_runtest(priv, (unsigned int)arg);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int jtag_open(struct inode *inode, struct file *file)
+{
+ struct jtag_info *jtag;
+
+ jtag = container_of(file->private_data, struct jtag_info, miscdev);
+
+ spin_lock(&jtag_file_lock);
+ if (jtag->is_open) {
+ spin_unlock(&jtag_file_lock);
+ return -EBUSY;
+ }
+
+ jtag->is_open = true;
+ file->private_data = jtag;
+
+ spin_unlock(&jtag_file_lock);
+
+ return 0;
+}
+
+static int jtag_release(struct inode *inode, struct file *file)
+{
+ struct jtag_info *jtag = file->private_data;
+
+ spin_lock(&jtag_file_lock);
+ jtag->is_open = false;
+ spin_unlock(&jtag_file_lock);
+
+ return 0;
+}
+
+const struct file_operations npcm_jtag_fops = {
+ .open = jtag_open,
+ .unlocked_ioctl = jtag_ioctl,
+ .release = jtag_release,
+};
+
+static int jtag_register_device(struct jtag_info *jtag)
+{
+ struct device *dev = jtag->dev;
+ int err;
+ int id;
+
+ if (!dev)
+ return -ENODEV;
+
+ id = ida_simple_get(&jtag_ida, 0, 0, GFP_KERNEL);
+ if (id < 0)
+ return id;
+
+ jtag->id = id;
+ /* register miscdev */
+ jtag->miscdev.parent = dev;
+ jtag->miscdev.fops = &npcm_jtag_fops;
+ jtag->miscdev.minor = MISC_DYNAMIC_MINOR;
+ jtag->miscdev.name = kasprintf(GFP_KERNEL, "jtag%d", id);
+ if (!jtag->miscdev.name) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ err = misc_register(&jtag->miscdev);
+ if (err) {
+ dev_err(jtag->miscdev.parent,
+ "Unable to register device, err %d\n", err);
+ kfree(jtag->miscdev.name);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ ida_simple_remove(&jtag_ida, id);
+ return err;
+}
+
+static int npcm7xx_jtag_init(struct device *dev, struct jtag_info *npcm7xx_jtag)
+{
+ struct pinctrl *pinctrl;
+ int i;
+
+ pinctrl = devm_pinctrl_get(dev);
+ if (IS_ERR(pinctrl))
+ return PTR_ERR(pinctrl);
+
+ npcm7xx_jtag->pinctrl = pinctrl;
+
+ /* jtag pins */
+ npcm7xx_jtag->pins[pin_TCK] = gpiod_get(dev, "tck", GPIOD_OUT_LOW);
+ npcm7xx_jtag->pins[pin_TDI] = gpiod_get(dev, "tdi", GPIOD_OUT_HIGH);
+ npcm7xx_jtag->pins[pin_TDO] = gpiod_get(dev, "tdo", GPIOD_IN);
+ npcm7xx_jtag->pins[pin_TMS] = gpiod_get(dev, "tms", GPIOD_OUT_HIGH);
+ for (i = 0; i < pin_NUM; i++) {
+ if (IS_ERR(npcm7xx_jtag->pins[i]))
+ return PTR_ERR(npcm7xx_jtag->pins[i]);
+ }
+
+ npcm7xx_jtag->freq = JTAG_PSPI_SPEED;
+ npcm7xx_jtag->tms_level = gpiod_get_value(npcm7xx_jtag->pins[pin_TMS]);
+ npcm7xx_jtag_set_tapstate(npcm7xx_jtag, JTAG_STATE_CURRENT, jtagtlr);
+ npcm7xx_jtag->mode = MODE_PSPI;
+
+ return 0;
+}
+
+static int npcm7xx_jtag_probe(struct spi_device *spi)
+{
+ struct jtag_info *npcm_jtag;
+ int ret;
+
+ dev_info(&spi->dev, "%s", __func__);
+
+ npcm_jtag = kzalloc(sizeof(struct jtag_info), GFP_KERNEL);
+ if (!npcm_jtag)
+ return -ENOMEM;
+
+ npcm_jtag->dev = &spi->dev;
+ npcm_jtag->spi = spi;
+ spi->mode = SPI_MODE_0 | SPI_NO_CS;
+
+ /* Initialize device*/
+ ret = npcm7xx_jtag_init(&spi->dev, npcm_jtag);
+ if (ret)
+ goto err;
+
+ /* Register a misc device */
+ ret = jtag_register_device(npcm_jtag);
+ if (ret) {
+ dev_err(&spi->dev, "failed to create device\n");
+ goto err;
+ }
+ spi_set_drvdata(spi, npcm_jtag);
+
+ return 0;
+err:
+ kfree(npcm_jtag);
+ return ret;
+}
+
+static int npcm7xx_jtag_remove(struct spi_device *spi)
+{
+ struct jtag_info *jtag = spi_get_drvdata(spi);
+ int i;
+
+ if (!jtag)
+ return 0;
+
+ misc_deregister(&jtag->miscdev);
+ kfree(jtag->miscdev.name);
+ for (i = 0; i < pin_NUM; i++) {
+ gpiod_direction_input(jtag->pins[i]);
+ gpiod_put(jtag->pins[i]);
+ }
+ kfree(jtag);
+ ida_simple_remove(&jtag_ida, jtag->id);
+
+ return 0;
+}
+
+static const struct of_device_id npcm7xx_jtag_of_match[] = {
+ { .compatible = "nuvoton,npcm750-jtag-master", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, npcm7xx_jtag_of_match);
+
+static struct spi_driver npcm7xx_jtag_driver = {
+ .driver = {
+ .name = "npcm7xx_jtag",
+ .of_match_table = npcm7xx_jtag_of_match,
+ },
+ .probe = npcm7xx_jtag_probe,
+ .remove = npcm7xx_jtag_remove,
+};
+
+module_spi_driver(npcm7xx_jtag_driver);
+
+MODULE_AUTHOR("Stanley Chu <yschu@nuvoton.com>");
+MODULE_DESCRIPTION("NPCM7xx JTAG Master Driver");
+MODULE_LICENSE("GPL");
+
--
2.22.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8
2021-01-05 13:44 [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Tomer Maimon
` (10 preceding siblings ...)
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 11/11] misc: npcm7xx-jtag-master: add NPCM7xx JTAG master driver Tomer Maimon
@ 2021-01-11 0:37 ` Joel Stanley
2021-01-11 19:30 ` Tomer Maimon
11 siblings, 1 reply; 20+ messages in thread
From: Joel Stanley @ 2021-01-11 0:37 UTC (permalink / raw)
To: Tomer Maimon; +Cc: Andrew Jeffery, OpenBMC Maillist, Benjamin Fair
Hi Tomer,
On Tue, 5 Jan 2021 at 13:45, Tomer Maimon <tmaimon77@gmail.com> wrote:
>
> In this patch set we will like to align with relevant modifications
> in Nuvoton OpenBMC Linux kernel 5.4.
Thanks for sending the patches. I can merge them into 5.8, however I
have a v5.10 branch that I plan on moving to imminently.
>
> Linux upstream current status:
> 1. npcm7xx clock driver - adding read only
> flag to divider clocks, Will be sent to Linux community.
> 2. Adding NPCM ADC calibration - Will be sent to Linux vanilla,
> but I am not sure it will be approved.
> 3. Add DT restart priority and reset type support - sent to Linux
> community la but havent approved yet.
> 4. persist configuration to the pin control driver - asked by a costumer,
> didnt sent to Linux community.
Do you plan on sending it?
> 5. Add HGPIO pin support to NPCM7xx pinctrl driver - will be sent
> to Linux community
> 6. JTAG master driver - will be sent to Linux community once we will
> have BMC folder.
As you've noted, I recommend you submit them to mainline ASAP to avoid
extra handling of patches in the openbmc tree.
Cheers,
Joel
>
> Changes since version 1:
> - Address comments from Jonathan Neuschäfer: removing trailing whitespace
> in NPCM watchdog documentation.
> - Adding Stanley Chu to NPCM JTAG master driver
>
> Tomer Maimon (11):
> clk: npcm7xx: add read only flag to divider clocks
> iio: adc: add calibration support to npcm ADC
> dts: npcm750: add fuse regmap support node
> watchdog: npcm: Add DT restart priority and reset type support
> dt-binding: watchdog: Add DT restart priority and reset type
> pinctrl: npcm7xx: Add HGPIO pin support to NPCM7xx pinctrl driver
> pinctrl: pinconf: add pin persist configuration
> pinctrl: npcm7xx: Add pin persist configuration support
> spi: npcm-pspi: Add full duplex support
> dt-binding: bmc: add NPCM7XX JTAG master documentation
> misc: npcm7xx-jtag-master: add NPCM7xx JTAG master driver
>
> .../bindings/bmc/npcm7xx-jtag-master.txt | 38 +
> .../bindings/watchdog/nuvoton,npcm-wdt.txt | 32 +
> arch/arm/boot/dts/nuvoton-common-npcm7xx.dtsi | 6 +
> drivers/clk/clk-npcm7xx.c | 70 +-
> drivers/iio/adc/npcm_adc.c | 191 ++++
> drivers/misc/Kconfig | 6 +
> drivers/misc/Makefile | 1 +
> drivers/misc/npcm7xx-jtag-master.c | 840 ++++++++++++++++++
> drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c | 130 ++-
> drivers/pinctrl/pinconf-generic.c | 3 +
> drivers/spi/spi-npcm-pspi.c | 75 +-
> drivers/watchdog/npcm_wdt.c | 121 ++-
> 12 files changed, 1418 insertions(+), 95 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/bmc/npcm7xx-jtag-master.txt
> create mode 100644 drivers/misc/npcm7xx-jtag-master.c
>
> --
> 2.22.0
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH linux dev-5.8 v2 02/11] iio: adc: add calibration support to npcm ADC
2021-01-05 13:44 ` [PATCH linux dev-5.8 v2 02/11] iio: adc: add calibration support to npcm ADC Tomer Maimon
@ 2021-01-11 0:52 ` Joel Stanley
0 siblings, 0 replies; 20+ messages in thread
From: Joel Stanley @ 2021-01-11 0:52 UTC (permalink / raw)
To: Tomer Maimon; +Cc: Andrew Jeffery, OpenBMC Maillist, Benjamin Fair
On Tue, 5 Jan 2021 at 13:45, Tomer Maimon <tmaimon77@gmail.com> wrote:
>
> Add calibration to improve accuracy measurement when using
> internal referance voltage.
reference
>
> the calibration values taken from the FUSE module.
>
> Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
I recommend taking a look at the proposed device tree changes before
we merge this one, so we don't have an incompatibility between future
code and device tree.
> ---
> drivers/iio/adc/npcm_adc.c | 191 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 191 insertions(+)
>
> diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c
> index 83bad2d5575d..02628b7eaca1 100644
> --- a/drivers/iio/adc/npcm_adc.c
> +++ b/drivers/iio/adc/npcm_adc.c
> @@ -17,6 +17,8 @@
> #include <linux/reset.h>
>
> struct npcm_adc {
> + u32 R05;
> + u32 R15;
> bool int_status;
> u32 adc_sample_hz;
> struct device *dev;
> @@ -51,6 +53,40 @@ struct npcm_adc {
> #define NPCM_RESOLUTION_BITS 10
> #define NPCM_INT_VREF_MV 2000
>
> +/* FUSE registers */
> +#define NPCM7XX_FST 0x00
> +#define NPCM7XX_FADDR 0x04
> +#define NPCM7XX_FDATA 0x08
> +#define NPCM7XX_FCFG 0x0C
> +#define NPCM7XX_FCTL 0x14
> +
> +/* FST Register Bits */
> +#define NPCM7XX_FST_RDY BIT(0)
> +#define NPCM7XX_FST_RDST BIT(1)
> +
> +/* FADDR Register Bits */
> +#define NPCM7XX_FADDR_BYTEADDR BIT(0)
> +#define NPCM7XX_FADDR_BYTEADDR_MASK GENMASK(9, 0)
> +
> +/* FADDR Register Bits */
> +#define NPCM7XX_FDATA_DATA BIT(0)
> +#define NPCM7XX_FDATA_CLEAN_VALUE BIT(1)
> +#define NPCM7XX_FDATA_DATA_MASK GENMASK(7, 0)
> +
> +/* FCTL Register Bits */
> +#define NPCM7XX_FCTL_RDST BIT(1)
> +
> +/* ADC Calibration Definition */
> +#define NPCM_INT_1500MV 768
> +#define NPCM_INT_1000MV 512
> +#define NPCM_ADC_MIN_VAL 0
> +#define NPCM_ADC_MAX_VAL 1023
> +
> +#define FUSE_CALIB_ADDR 24
> +#define FUSE_CALIB_SIZE 8
> +#define DATA_CALIB_SIZE 4
> +#define FUSE_READ_TIMEOUT 0xDEADBEEF
> +
> #define NPCM_ADC_CHAN(ch) { \
> .type = IIO_VOLTAGE, \
> .indexed = 1, \
> @@ -71,6 +107,133 @@ static const struct iio_chan_spec npcm_adc_iio_channels[] = {
> NPCM_ADC_CHAN(7),
> };
>
> +static int npcm750_fuse_wait_for_ready(struct regmap *fuse_regmap, u32 timeout)
> +{
> + u32 time = timeout;
> + u32 fstreg;
> +
> + while (--time > 1) {
> + regmap_read(fuse_regmap, NPCM7XX_FST, &fstreg);
regmap_read_poll_timeout
> + if (fstreg & NPCM7XX_FST_RDY) {
> + regmap_write_bits(fuse_regmap, NPCM7XX_FST,
> + NPCM7XX_FST_RDST, NPCM7XX_FST_RDST);
> + return 0;
> + }
> + }
> +
> + /* try to clear the status in case it was set */
> + regmap_write_bits(fuse_regmap, NPCM7XX_FST, NPCM7XX_FST_RDST,
> + NPCM7XX_FST_RDST);
> +
> + return -EINVAL;
> +}
> +
> +static void npcm750_fuse_read(struct regmap *fuse_regmap, u32 addr, u8 *data)
> +{
> + u32 val;
> +
> + npcm750_fuse_wait_for_ready(fuse_regmap, FUSE_READ_TIMEOUT);
This ignores the time out.
> +
> + regmap_write_bits(fuse_regmap, NPCM7XX_FADDR,
> + NPCM7XX_FADDR_BYTEADDR_MASK, addr);
> + regmap_read(fuse_regmap, NPCM7XX_FADDR, &val);
> + regmap_write(fuse_regmap, NPCM7XX_FCTL, NPCM7XX_FCTL_RDST);
> +
> + npcm750_fuse_wait_for_ready(fuse_regmap, FUSE_READ_TIMEOUT);
...as does this.
> + regmap_read(fuse_regmap, NPCM7XX_FDATA, &val);
> + *data = (u8)val;
> +
> + regmap_write_bits(fuse_regmap, NPCM7XX_FDATA, NPCM7XX_FDATA_DATA_MASK,
> + NPCM7XX_FDATA_CLEAN_VALUE);
> +}
> +
> +static int npcm750_ECC_to_nibble(u8 ECC, u8 nibble)
> +{
> + u8 nibble_b0 = (nibble >> 0) & BIT(0);
> + u8 nibble_b1 = (nibble >> 1) & BIT(0);
> + u8 nibble_b2 = (nibble >> 2) & BIT(0);
> + u8 nibble_b3 = (nibble >> 3) & BIT(0);
> + u8 tmp_ECC = nibble;
> +
> + tmp_ECC |= (nibble_b0 ^ nibble_b1) << 4 | (nibble_b2 ^ nibble_b3) << 5 |
> + (nibble_b0 ^ nibble_b2) << 6 | (nibble_b1 ^ nibble_b3) << 7;
> +
> + if (tmp_ECC != ECC)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +static int npcm750_ECC_to_byte(u16 ECC, u8 *Byte)
> +{
> + u8 nibble_L, nibble_H;
> + u8 ECC_L, ECC_H;
> +
> + ECC_H = ECC >> 8;
> + nibble_H = ECC_H & 0x0F;
> + ECC_L = ECC >> 0;
> + nibble_L = ECC_L & 0x0F;
> +
> + if (npcm750_ECC_to_nibble(ECC_H, nibble_H) != 0 ||
> + npcm750_ECC_to_nibble(ECC_L, nibble_L) != 0)
> + return -EINVAL;
> +
> + *Byte = nibble_H << 4 | nibble_L << 0;
> +
> + return 0;
> +}
> +
> +static int npcm750_read_nibble_parity(u8 *block_ECC, u8 *ADC_calib)
> +{
> + int i;
> + u16 ECC;
> +
> + for (i = 0; i < DATA_CALIB_SIZE; i++) {
> + memcpy(&ECC, block_ECC + (i * 2), 2);
> + if (npcm750_ECC_to_byte(ECC, &ADC_calib[i]) != 0)
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int npcm750_fuse_calibration_read(struct platform_device *pdev,
> + struct npcm_adc *info)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + struct regmap *fuse_regmap;
> + ssize_t bytes_read = 0;
> + u8 read_buf[8];
> + u32 ADC_calib;
> + u32 addr = FUSE_CALIB_ADDR;
> +
> + if (of_device_is_compatible(np, "nuvoton,npcm750-adc")) {
This will always be true.
> + fuse_regmap = syscon_regmap_lookup_by_compatible
> + ("nuvoton,npcm750-fuse");
If you use a phandle to the fuse node, you can have the one code base
support multiple families of chips. Use
syscon_regmap_lookup_by_phandle(np, "syscon")
and in your device tree:
adc: adc@c000 {
compatible = "nuvoton,npcm750-adc";
reg = <0xc000 0x8>;
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk NPCM7XX_CLK_ADC>;
resets = <&rstc NPCM7XX_RESET_IPSRST1
NPCM7XX_RESET_ADC>;
syscon = <&fuse_syscon>;
};
> + if (IS_ERR(fuse_regmap)) {
> + dev_warn(&pdev->dev, "Failed to find nuvoton,npcm750-fuse\n");
> + return PTR_ERR(fuse_regmap);
> + }
> +
> + while (bytes_read < FUSE_CALIB_SIZE) {
> + npcm750_fuse_read(fuse_regmap, addr,
> + &read_buf[bytes_read]);
> + bytes_read++;
> + addr++;
> + }
> +
> + if (npcm750_read_nibble_parity(read_buf, (u8 *)&ADC_calib)) {
> + dev_warn(info->dev, "FUSE Clibration read failed\n");
calibration
> + return -EINVAL;
> + }
> +
> + info->R05 = ADC_calib & 0xFFFF;
> + info->R15 = ADC_calib >> 16;
> + }
> +
> + return 0;
> +}
> +
> static irqreturn_t npcm_adc_isr(int irq, void *data)
> {
> u32 regtemp;
> @@ -125,6 +288,29 @@ static int npcm_adc_read(struct npcm_adc *info, int *val, u8 channel)
> return 0;
> }
>
> +static void npcm_adc_calibration(int *val, struct npcm_adc *info)
> +{
> + int mul_val;
> + int offset_val;
> +
> + mul_val = NPCM_INT_1000MV * (*val - info->R15);
> + if (mul_val < 0) {
> + mul_val = mul_val * -1;
> + offset_val = DIV_ROUND_CLOSEST(mul_val,
> + (info->R15 - info->R05));
> + *val = NPCM_INT_1500MV - offset_val;
> + } else {
> + offset_val = DIV_ROUND_CLOSEST(mul_val,
> + (info->R15 - info->R05));
> + *val = NPCM_INT_1500MV + offset_val;
> + }
> +
> + if (*val < NPCM_ADC_MIN_VAL)
> + *val = NPCM_ADC_MIN_VAL;
> + if (*val > NPCM_ADC_MAX_VAL)
> + *val = NPCM_ADC_MAX_VAL;
> +}
> +
> static int npcm_adc_read_raw(struct iio_dev *indio_dev,
> struct iio_chan_spec const *chan, int *val,
> int *val2, long mask)
> @@ -142,6 +328,10 @@ static int npcm_adc_read_raw(struct iio_dev *indio_dev,
> dev_err(info->dev, "NPCM ADC read failed\n");
> return ret;
> }
> +
> + if ((info->R05 || info->R15) && IS_ERR(info->vref))
> + npcm_adc_calibration(val, info);
> +
> return IIO_VAL_INT;
> case IIO_CHAN_INFO_SCALE:
> if (!IS_ERR(info->vref)) {
> @@ -248,6 +438,7 @@ static int npcm_adc_probe(struct platform_device *pdev)
> info->regs + NPCM_ADCCON);
> }
>
> + npcm750_fuse_calibration_read(pdev, info);
> init_waitqueue_head(&info->wq);
>
> reg_con = ioread32(info->regs + NPCM_ADCCON);
> --
> 2.22.0
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH linux dev-5.8 v2 04/11] watchdog: npcm: Add DT restart priority and reset type support
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 04/11] watchdog: npcm: Add DT restart priority and reset type support Tomer Maimon
@ 2021-01-11 0:55 ` Joel Stanley
2021-01-11 19:22 ` Tomer Maimon
0 siblings, 1 reply; 20+ messages in thread
From: Joel Stanley @ 2021-01-11 0:55 UTC (permalink / raw)
To: Tomer Maimon; +Cc: Andrew Jeffery, OpenBMC Maillist, Benjamin Fair
On Tue, 5 Jan 2021 at 13:45, Tomer Maimon <tmaimon77@gmail.com> wrote:
>
> Add Device tree restart priority and
> three reset types support.
>
> Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
Can you remind me the history of this change. Was a similar patch
rejected by mainline?
> ---
> drivers/watchdog/npcm_wdt.c | 121 +++++++++++++++++++++++++++++++++++-
> 1 file changed, 119 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/watchdog/npcm_wdt.c b/drivers/watchdog/npcm_wdt.c
> index 765577f11c8d..bbf27da34834 100644
> --- a/drivers/watchdog/npcm_wdt.c
> +++ b/drivers/watchdog/npcm_wdt.c
> @@ -11,7 +11,24 @@
> #include <linux/platform_device.h>
> #include <linux/slab.h>
> #include <linux/watchdog.h>
> -
> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +
> +/* NPCM7xx GCR module */
> +#define NPCM7XX_RESSR_OFFSET 0x6C
> +#define NPCM7XX_INTCR2_OFFSET 0x60
> +
> +#define NPCM7XX_PORST BIT(31)
> +#define NPCM7XX_CORST BIT(30)
> +#define NPCM7XX_WD0RST BIT(29)
> +#define NPCM7XX_WD1RST BIT(24)
> +#define NPCM7XX_WD2RST BIT(23)
> +#define NPCM7XX_SWR1RST BIT(28)
> +#define NPCM7XX_SWR2RST BIT(27)
> +#define NPCM7XX_SWR3RST BIT(26)
> +#define NPCM7XX_SWR4RST BIT(25)
> +
> + /* WD register */
> #define NPCM_WTCR 0x1C
>
> #define NPCM_WTCLK (BIT(10) | BIT(11)) /* Clock divider */
> @@ -43,6 +60,10 @@
> struct npcm_wdt {
> struct watchdog_device wdd;
> void __iomem *reg;
> + u32 card_reset;
> + u32 ext1_reset;
> + u32 ext2_reset;
> +
> };
>
> static inline struct npcm_wdt *to_npcm_wdt(struct watchdog_device *wdd)
> @@ -176,14 +197,70 @@ static const struct watchdog_ops npcm_wdt_ops = {
> .restart = npcm_wdt_restart,
> };
>
> +static void npcm_get_reset_status(struct npcm_wdt *wdt, struct device *dev)
> +{
> + struct regmap *gcr_regmap;
> + u32 rstval;
> +
> + if (of_device_is_compatible(dev->of_node, "nuvoton,npcm750-wdt")) {
> + gcr_regmap = syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr");
This will have the same issues as the ADC with supporting multiple
families of chip with the same code. I suggest you adjust it to use
the phandle approach.
> + if (IS_ERR(gcr_regmap)) {
> + dev_warn(dev, "Failed to find nuvoton,npcm750-gcr WD reset status not supported\n");
> + }
> +
> + regmap_read(gcr_regmap, NPCM7XX_RESSR_OFFSET, &rstval);
> + if (!rstval) {
> + regmap_read(gcr_regmap, NPCM7XX_INTCR2_OFFSET, &rstval);
> + rstval = ~rstval;
> + }
> +
> + if(rstval & wdt->card_reset)
> + wdt->wdd.bootstatus |= WDIOF_CARDRESET;
> + if(rstval & wdt->ext1_reset)
> + wdt->wdd.bootstatus |= WDIOF_EXTERN1;
> + if(rstval & wdt->ext2_reset)
> + wdt->wdd.bootstatus |= WDIOF_EXTERN2;
> + }
> +
> +}
> +
> +static u32 npcm_wdt_reset_type(const char *reset_type)
> +{
> + if (!strcmp(reset_type, "porst"))
> + return NPCM7XX_PORST;
> + else if (!strcmp(reset_type, "corst"))
> + return NPCM7XX_CORST;
> + else if (!strcmp(reset_type, "wd0"))
> + return NPCM7XX_WD0RST;
> + else if (!strcmp(reset_type, "wd1"))
> + return NPCM7XX_WD1RST;
> + else if (!strcmp(reset_type, "wd2"))
> + return NPCM7XX_WD2RST;
> + else if (!strcmp(reset_type, "sw1"))
> + return NPCM7XX_SWR1RST;
> + else if (!strcmp(reset_type, "sw2"))
> + return NPCM7XX_SWR2RST;
> + else if (!strcmp(reset_type, "sw3"))
> + return NPCM7XX_SWR3RST;
> + else if (!strcmp(reset_type, "sw4"))
> + return NPCM7XX_SWR4RST;
> +
> + return 0;
> +}
> +
> static int npcm_wdt_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> + const char *card_reset_type;
> + const char *ext1_reset_type;
> + const char *ext2_reset_type;
> struct npcm_wdt *wdt;
> + struct resource *res;
> + u32 priority;
> int irq;
> int ret;
>
> - wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
> + wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
> if (!wdt)
> return -ENOMEM;
>
> @@ -195,6 +272,45 @@ static int npcm_wdt_probe(struct platform_device *pdev)
> if (irq < 0)
> return irq;
>
> + if (of_property_read_u32(pdev->dev.of_node, "nuvoton,restart-priority",
> + &priority))
> + watchdog_set_restart_priority(&wdt->wdd, 128);
> + else
> + watchdog_set_restart_priority(&wdt->wdd, priority);
> +
> + ret = of_property_read_string(pdev->dev.of_node,
> + "nuvoton,card-reset-type",
> + &card_reset_type);
> + if (ret)
> + wdt->card_reset = NPCM7XX_PORST;
> + else {
> + wdt->card_reset = npcm_wdt_reset_type(card_reset_type);
> + if (!wdt->card_reset)
> + wdt->card_reset = NPCM7XX_PORST;
> + }
> +
> + ret = of_property_read_string(pdev->dev.of_node,
> + "nuvoton,ext1-reset-type",
> + &ext1_reset_type);
> + if (ret)
> + wdt->ext1_reset = NPCM7XX_WD0RST;
> + else {
> + wdt->ext1_reset = npcm_wdt_reset_type(ext1_reset_type);
> + if (!wdt->ext1_reset)
> + wdt->ext1_reset = NPCM7XX_WD0RST;
> + }
> +
> + ret = of_property_read_string(pdev->dev.of_node,
> + "nuvoton,ext2-reset-type",
> + &ext2_reset_type);
> + if (ret)
> + wdt->ext2_reset = NPCM7XX_SWR1RST;
> + else {
> + wdt->ext2_reset = npcm_wdt_reset_type(ext2_reset_type);
> + if (!wdt->ext2_reset)
> + wdt->ext2_reset = NPCM7XX_SWR1RST;
> + }
> +
> wdt->wdd.info = &npcm_wdt_info;
> wdt->wdd.ops = &npcm_wdt_ops;
> wdt->wdd.min_timeout = 1;
> @@ -213,6 +329,7 @@ static int npcm_wdt_probe(struct platform_device *pdev)
> set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
> }
>
> + npcm_get_reset_status(wdt, dev);
> ret = devm_request_irq(dev, irq, npcm_wdt_interrupt, 0, "watchdog",
> wdt);
> if (ret)
> --
> 2.22.0
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH linux dev-5.8 v2 06/11] pinctrl: npcm7xx: Add HGPIO pin support to NPCM7xx pinctrl driver
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 06/11] pinctrl: npcm7xx: Add HGPIO pin support to NPCM7xx pinctrl driver Tomer Maimon
@ 2021-01-11 0:56 ` Joel Stanley
0 siblings, 0 replies; 20+ messages in thread
From: Joel Stanley @ 2021-01-11 0:56 UTC (permalink / raw)
To: Tomer Maimon; +Cc: Andrew Jeffery, OpenBMC Maillist, Benjamin Fair
On Tue, 5 Jan 2021 at 13:45, Tomer Maimon <tmaimon77@gmail.com> wrote:
>
> Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
Reviewed-by: Joel Stanley <joel@jms.id.au>
This one should go upstream asap.
> ---
> drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c | 65 +++++++++++++++++------
> 1 file changed, 49 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
> index a935065cdac4..e5f58ea89917 100644
> --- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
> +++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
> @@ -504,6 +504,15 @@ static const int lkgpo2_pins[] = { 9 };
>
> static const int nprd_smi_pins[] = { 190 };
>
> +static const int hgpio0_pins[] = { 20 };
> +static const int hgpio1_pins[] = { 21 };
> +static const int hgpio2_pins[] = { 22 };
> +static const int hgpio3_pins[] = { 23 };
> +static const int hgpio4_pins[] = { 24 };
> +static const int hgpio5_pins[] = { 25 };
> +static const int hgpio6_pins[] = { 59 };
> +static const int hgpio7_pins[] = { 60 };
> +
> /*
> * pin: name, number
> * group: name, npins, pins
> @@ -631,6 +640,14 @@ struct npcm7xx_group {
> NPCM7XX_GRP(lkgpo1), \
> NPCM7XX_GRP(lkgpo2), \
> NPCM7XX_GRP(nprd_smi), \
> + NPCM7XX_GRP(hgpio0), \
> + NPCM7XX_GRP(hgpio1), \
> + NPCM7XX_GRP(hgpio2), \
> + NPCM7XX_GRP(hgpio3), \
> + NPCM7XX_GRP(hgpio4), \
> + NPCM7XX_GRP(hgpio5), \
> + NPCM7XX_GRP(hgpio6), \
> + NPCM7XX_GRP(hgpio7), \
> \
>
> enum {
> @@ -774,6 +791,14 @@ NPCM7XX_SFUNC(lkgpo0);
> NPCM7XX_SFUNC(lkgpo1);
> NPCM7XX_SFUNC(lkgpo2);
> NPCM7XX_SFUNC(nprd_smi);
> +NPCM7XX_SFUNC(hgpio0);
> +NPCM7XX_SFUNC(hgpio1);
> +NPCM7XX_SFUNC(hgpio2);
> +NPCM7XX_SFUNC(hgpio3);
> +NPCM7XX_SFUNC(hgpio4);
> +NPCM7XX_SFUNC(hgpio5);
> +NPCM7XX_SFUNC(hgpio6);
> +NPCM7XX_SFUNC(hgpio7);
>
> /* Function names */
> static struct npcm7xx_func npcm7xx_funcs[] = {
> @@ -892,6 +917,14 @@ static struct npcm7xx_func npcm7xx_funcs[] = {
> NPCM7XX_MKFUNC(lkgpo1),
> NPCM7XX_MKFUNC(lkgpo2),
> NPCM7XX_MKFUNC(nprd_smi),
> + NPCM7XX_MKFUNC(hgpio0),
> + NPCM7XX_MKFUNC(hgpio1),
> + NPCM7XX_MKFUNC(hgpio2),
> + NPCM7XX_MKFUNC(hgpio3),
> + NPCM7XX_MKFUNC(hgpio4),
> + NPCM7XX_MKFUNC(hgpio5),
> + NPCM7XX_MKFUNC(hgpio6),
> + NPCM7XX_MKFUNC(hgpio7),
> };
>
> #define NPCM7XX_PINCFG(a, b, c, d, e, f, g, h, i, j, k) \
> @@ -944,12 +977,12 @@ static const struct npcm7xx_pincfg pincfg[] = {
> NPCM7XX_PINCFG(17, pspi2, MFSEL3, 13, smb4den, I2CSEGSEL, 23, none, NONE, 0, DS(8, 12)),
> NPCM7XX_PINCFG(18, pspi2, MFSEL3, 13, smb4b, I2CSEGSEL, 14, none, NONE, 0, DS(8, 12)),
> NPCM7XX_PINCFG(19, pspi2, MFSEL3, 13, smb4b, I2CSEGSEL, 14, none, NONE, 0, DS(8, 12)),
> - NPCM7XX_PINCFG(20, smb4c, I2CSEGSEL, 15, smb15, MFSEL3, 8, none, NONE, 0, 0),
> - NPCM7XX_PINCFG(21, smb4c, I2CSEGSEL, 15, smb15, MFSEL3, 8, none, NONE, 0, 0),
> - NPCM7XX_PINCFG(22, smb4d, I2CSEGSEL, 16, smb14, MFSEL3, 7, none, NONE, 0, 0),
> - NPCM7XX_PINCFG(23, smb4d, I2CSEGSEL, 16, smb14, MFSEL3, 7, none, NONE, 0, 0),
> - NPCM7XX_PINCFG(24, ioxh, MFSEL3, 18, none, NONE, 0, none, NONE, 0, DS(8, 12)),
> - NPCM7XX_PINCFG(25, ioxh, MFSEL3, 18, none, NONE, 0, none, NONE, 0, DS(8, 12)),
> + NPCM7XX_PINCFG(20, hgpio0, MFSEL2, 24, smb15, MFSEL3, 8, smb4c, I2CSEGSEL, 15, 0),
> + NPCM7XX_PINCFG(21, hgpio1, MFSEL2, 25, smb15, MFSEL3, 8, smb4c, I2CSEGSEL, 15, 0),
> + NPCM7XX_PINCFG(22, hgpio2, MFSEL2, 26, smb14, MFSEL3, 7, smb4d, I2CSEGSEL, 16, 0),
> + NPCM7XX_PINCFG(23, hgpio3, MFSEL2, 27, smb14, MFSEL3, 7, smb4d, I2CSEGSEL, 16, 0),
> + NPCM7XX_PINCFG(24, hgpio4, MFSEL2, 28, ioxh, MFSEL3, 18, none, NONE, 0, DS(8, 12)),
> + NPCM7XX_PINCFG(25, hgpio5, MFSEL2, 29, ioxh, MFSEL3, 18, none, NONE, 0, DS(8, 12)),
> NPCM7XX_PINCFG(26, smb5, MFSEL1, 2, none, NONE, 0, none, NONE, 0, 0),
> NPCM7XX_PINCFG(27, smb5, MFSEL1, 2, none, NONE, 0, none, NONE, 0, 0),
> NPCM7XX_PINCFG(28, smb4, MFSEL1, 1, none, NONE, 0, none, NONE, 0, 0),
> @@ -982,8 +1015,8 @@ static const struct npcm7xx_pincfg pincfg[] = {
> NPCM7XX_PINCFG(56, r1err, MFSEL1, 12, none, NONE, 0, none, NONE, 0, 0),
> NPCM7XX_PINCFG(57, r1md, MFSEL1, 13, none, NONE, 0, none, NONE, 0, DS(2, 4)),
> NPCM7XX_PINCFG(58, r1md, MFSEL1, 13, none, NONE, 0, none, NONE, 0, DS(2, 4)),
> - NPCM7XX_PINCFG(59, smb3d, I2CSEGSEL, 13, none, NONE, 0, none, NONE, 0, 0),
> - NPCM7XX_PINCFG(60, smb3d, I2CSEGSEL, 13, none, NONE, 0, none, NONE, 0, 0),
> + NPCM7XX_PINCFG(59, hgpio6, MFSEL2, 30, smb3d, I2CSEGSEL, 13, none, NONE, 0, 0),
> + NPCM7XX_PINCFG(60, hgpio7, MFSEL2, 31, smb3d, I2CSEGSEL, 13, none, NONE, 0, 0),
> NPCM7XX_PINCFG(61, uart1, MFSEL1, 10, none, NONE, 0, none, NONE, 0, GPO),
> NPCM7XX_PINCFG(62, uart1, MFSEL1, 10, bmcuart1, MFSEL3, 24, none, NONE, 0, GPO),
> NPCM7XX_PINCFG(63, uart1, MFSEL1, 10, bmcuart1, MFSEL3, 24, none, NONE, 0, GPO),
> @@ -1188,12 +1221,12 @@ static const struct pinctrl_pin_desc npcm7xx_pins[] = {
> PINCTRL_PIN(17, "GPIO17/PSPI2DI/SMB4DEN"),
> PINCTRL_PIN(18, "GPIO18/PSPI2D0/SMB4BSDA"),
> PINCTRL_PIN(19, "GPIO19/PSPI2CK/SMB4BSCL"),
> - PINCTRL_PIN(20, "GPIO20/SMB4CSDA/SMB15SDA"),
> - PINCTRL_PIN(21, "GPIO21/SMB4CSCL/SMB15SCL"),
> - PINCTRL_PIN(22, "GPIO22/SMB4DSDA/SMB14SDA"),
> - PINCTRL_PIN(23, "GPIO23/SMB4DSCL/SMB14SCL"),
> - PINCTRL_PIN(24, "GPIO24/IOXHDO"),
> - PINCTRL_PIN(25, "GPIO25/IOXHDI"),
> + PINCTRL_PIN(20, "GPIO20/HGPIO0/SMB4CSDA/SMB15SDA"),
> + PINCTRL_PIN(21, "GPIO21/HGPIO1/SMB4CSCL/SMB15SCL"),
> + PINCTRL_PIN(22, "GPIO22/HGPIO2/SMB4DSDA/SMB14SDA"),
> + PINCTRL_PIN(23, "GPIO23/HGPIO3/SMB4DSCL/SMB14SCL"),
> + PINCTRL_PIN(24, "GPIO24/HGPIO4/IOXHDO"),
> + PINCTRL_PIN(25, "GPIO25/HGPIO5/IOXHDI"),
> PINCTRL_PIN(26, "GPIO26/SMB5SDA"),
> PINCTRL_PIN(27, "GPIO27/SMB5SCL"),
> PINCTRL_PIN(28, "GPIO28/SMB4SDA"),
> @@ -1226,8 +1259,8 @@ static const struct pinctrl_pin_desc npcm7xx_pins[] = {
> PINCTRL_PIN(56, "GPIO56/R1RXERR"),
> PINCTRL_PIN(57, "GPIO57/R1MDC"),
> PINCTRL_PIN(58, "GPIO58/R1MDIO"),
> - PINCTRL_PIN(59, "GPIO59/SMB3DSDA"),
> - PINCTRL_PIN(60, "GPIO60/SMB3DSCL"),
> + PINCTRL_PIN(59, "GPIO59/HGPIO6/SMB3DSDA"),
> + PINCTRL_PIN(60, "GPIO60/HGPIO7/SMB3DSCL"),
> PINCTRL_PIN(61, "GPO61/nDTR1_BOUT1/STRAP6"),
> PINCTRL_PIN(62, "GPO62/nRTST1/STRAP5"),
> PINCTRL_PIN(63, "GPO63/TXD1/STRAP4"),
> --
> 2.22.0
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH linux dev-5.8 v2 09/11] spi: npcm-pspi: Add full duplex support
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 09/11] spi: npcm-pspi: Add full duplex support Tomer Maimon
@ 2021-01-11 1:04 ` Joel Stanley
2021-01-11 10:58 ` Avi Fishman
0 siblings, 1 reply; 20+ messages in thread
From: Joel Stanley @ 2021-01-11 1:04 UTC (permalink / raw)
To: Tomer Maimon; +Cc: Andrew Jeffery, OpenBMC Maillist, Benjamin Fair
On Tue, 5 Jan 2021 at 13:45, Tomer Maimon <tmaimon77@gmail.com> wrote:
>
> Modify the IRQ handler in the NPCM PSPI
> driver to support SPI full duplex communication.
>
> Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
> ---
> drivers/spi/spi-npcm-pspi.c | 75 +++++++++++++++----------------------
> 1 file changed, 30 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c
> index 87cd0233c60b..92fae0b23eb1 100644
> --- a/drivers/spi/spi-npcm-pspi.c
> +++ b/drivers/spi/spi-npcm-pspi.c
> @@ -197,22 +197,22 @@ static void npcm_pspi_setup_transfer(struct spi_device *spi,
> static void npcm_pspi_send(struct npcm_pspi *priv)
> {
> int wsize;
> - u16 val;
> + u16 val = 0;
>
> wsize = min(bytes_per_word(priv->bits_per_word), priv->tx_bytes);
> priv->tx_bytes -= wsize;
>
> - if (!priv->tx_buf)
> - return;
It looks like you're removing this check and instead doing it inside
each case. That seems like a waste, why not leave the single check in?
> -
> switch (wsize) {
> case 1:
> - val = *priv->tx_buf++;
> + if (priv->tx_buf)
> + val = *priv->tx_buf++;
> iowrite8(val, NPCM_PSPI_DATA + priv->base);
> break;
> case 2:
> - val = *priv->tx_buf++;
> - val = *priv->tx_buf++ | (val << 8);
> + if (priv->tx_buf) {
> + val = *priv->tx_buf++;
> + val = *priv->tx_buf++ | (val << 8);
> + }
> iowrite16(val, NPCM_PSPI_DATA + priv->base);
> break;
> default:
> @@ -224,22 +224,24 @@ static void npcm_pspi_send(struct npcm_pspi *priv)
> static void npcm_pspi_recv(struct npcm_pspi *priv)
> {
> int rsize;
> - u16 val;
> + u16 val_16;
> + u8 val_8;
>
> rsize = min(bytes_per_word(priv->bits_per_word), priv->rx_bytes);
> priv->rx_bytes -= rsize;
>
> - if (!priv->rx_buf)
> - return;
> -
> switch (rsize) {
> case 1:
> - *priv->rx_buf++ = ioread8(priv->base + NPCM_PSPI_DATA);
> + val_8 = ioread8(priv->base + NPCM_PSPI_DATA);
> + if (priv->rx_buf)
> + *priv->rx_buf++ = val_8;
> break;
> case 2:
> - val = ioread16(priv->base + NPCM_PSPI_DATA);
> - *priv->rx_buf++ = (val >> 8);
> - *priv->rx_buf++ = val & 0xff;
> + val_16 = ioread16(priv->base + NPCM_PSPI_DATA);
> + if (priv->rx_buf) {
> + *priv->rx_buf++ = (val_16 >> 8);
> + *priv->rx_buf++ = val_16 & 0xff;
> + }
> break;
> default:
> WARN_ON_ONCE(1);
> @@ -298,43 +300,26 @@ static irqreturn_t npcm_pspi_handler(int irq, void *dev_id)
> struct npcm_pspi *priv = dev_id;
> u8 stat;
>
> - stat = ioread8(priv->base + NPCM_PSPI_STAT);
> -
> if (!priv->tx_buf && !priv->rx_buf)
> return IRQ_NONE;
>
> - if (priv->tx_buf) {
> - if (stat & NPCM_PSPI_STAT_RBF) {
> - ioread8(NPCM_PSPI_DATA + priv->base);
> - if (priv->tx_bytes == 0) {
> - npcm_pspi_disable(priv);
> - complete(&priv->xfer_done);
> - return IRQ_HANDLED;
> - }
> - }
> -
> - if ((stat & NPCM_PSPI_STAT_BSY) == 0)
> - if (priv->tx_bytes)
> - npcm_pspi_send(priv);
> + if (priv->tx_bytes == 0 && priv->rx_bytes == 0) {
> + npcm_pspi_disable(priv);
> + complete(&priv->xfer_done);
> + return IRQ_HANDLED;
> }
>
> - if (priv->rx_buf) {
> - if (stat & NPCM_PSPI_STAT_RBF) {
> - if (!priv->rx_bytes)
> - return IRQ_NONE;
> -
> - npcm_pspi_recv(priv);
> + stat = ioread8(priv->base + NPCM_PSPI_STAT);
>
> - if (!priv->rx_bytes) {
> - npcm_pspi_disable(priv);
> - complete(&priv->xfer_done);
> - return IRQ_HANDLED;
> - }
> - }
> + /*
> + * first we do the read since if we do the write we previous read might
> + * be lost (indeed low chances)
> + */
> + if ((stat & NPCM_PSPI_STAT_RBF) && priv->rx_bytes)
> + npcm_pspi_recv(priv);
>
> - if (((stat & NPCM_PSPI_STAT_BSY) == 0) && !priv->tx_buf)
> - iowrite8(0x0, NPCM_PSPI_DATA + priv->base);
> - }
> + if (((stat & NPCM_PSPI_STAT_BSY) == 0) && priv->tx_bytes)
> + npcm_pspi_send(priv);
>
> return IRQ_HANDLED;
> }
> --
> 2.22.0
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH linux dev-5.8 v2 09/11] spi: npcm-pspi: Add full duplex support
2021-01-11 1:04 ` Joel Stanley
@ 2021-01-11 10:58 ` Avi Fishman
0 siblings, 0 replies; 20+ messages in thread
From: Avi Fishman @ 2021-01-11 10:58 UTC (permalink / raw)
To: Joel Stanley
Cc: Andrew Jeffery, OpenBMC Maillist, Tomer Maimon, Benjamin Fair
On Mon, Jan 11, 2021 at 3:05 AM Joel Stanley <joel@jms.id.au> wrote:
>
> On Tue, 5 Jan 2021 at 13:45, Tomer Maimon <tmaimon77@gmail.com> wrote:
> >
> > Modify the IRQ handler in the NPCM PSPI
> > driver to support SPI full duplex communication.
> >
> > Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
> > ---
> > drivers/spi/spi-npcm-pspi.c | 75 +++++++++++++++----------------------
> > 1 file changed, 30 insertions(+), 45 deletions(-)
> >
> > diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c
> > index 87cd0233c60b..92fae0b23eb1 100644
> > --- a/drivers/spi/spi-npcm-pspi.c
> > +++ b/drivers/spi/spi-npcm-pspi.c
> > @@ -197,22 +197,22 @@ static void npcm_pspi_setup_transfer(struct spi_device *spi,
> > static void npcm_pspi_send(struct npcm_pspi *priv)
> > {
> > int wsize;
> > - u16 val;
> > + u16 val = 0;
> >
> > wsize = min(bytes_per_word(priv->bits_per_word), priv->tx_bytes);
> > priv->tx_bytes -= wsize;
> >
> > - if (!priv->tx_buf)
> > - return;
>
> It looks like you're removing this check and instead doing it inside
> each case. That seems like a waste, why not leave the single check in?
Even if the tx_buf is NULL, I still need to do the write to
NPCM_PSPI_DATA, since only this write triggers the clock and I need
the clocks for the rx_buf.
and this is why I initialized 'val = 0'
>
> > -
> > switch (wsize) {
> > case 1:
> > - val = *priv->tx_buf++;
> > + if (priv->tx_buf)
> > + val = *priv->tx_buf++;
> > iowrite8(val, NPCM_PSPI_DATA + priv->base);
> > break;
> > case 2:
> > - val = *priv->tx_buf++;
> > - val = *priv->tx_buf++ | (val << 8);
> > + if (priv->tx_buf) {
> > + val = *priv->tx_buf++;
> > + val = *priv->tx_buf++ | (val << 8);
> > + }
> > iowrite16(val, NPCM_PSPI_DATA + priv->base);
> > break;
> > default:
> > @@ -224,22 +224,24 @@ static void npcm_pspi_send(struct npcm_pspi *priv)
> > static void npcm_pspi_recv(struct npcm_pspi *priv)
> > {
> > int rsize;
> > - u16 val;
> > + u16 val_16;
> > + u8 val_8;
> >
> > rsize = min(bytes_per_word(priv->bits_per_word), priv->rx_bytes);
> > priv->rx_bytes -= rsize;
> >
> > - if (!priv->rx_buf)
> > - return;
> > -
> > switch (rsize) {
> > case 1:
> > - *priv->rx_buf++ = ioread8(priv->base + NPCM_PSPI_DATA);
> > + val_8 = ioread8(priv->base + NPCM_PSPI_DATA);
> > + if (priv->rx_buf)
> > + *priv->rx_buf++ = val_8;
> > break;
> > case 2:
> > - val = ioread16(priv->base + NPCM_PSPI_DATA);
> > - *priv->rx_buf++ = (val >> 8);
> > - *priv->rx_buf++ = val & 0xff;
> > + val_16 = ioread16(priv->base + NPCM_PSPI_DATA);
> > + if (priv->rx_buf) {
> > + *priv->rx_buf++ = (val_16 >> 8);
> > + *priv->rx_buf++ = val_16 & 0xff;
> > + }
> > break;
> > default:
> > WARN_ON_ONCE(1);
> > @@ -298,43 +300,26 @@ static irqreturn_t npcm_pspi_handler(int irq, void *dev_id)
> > struct npcm_pspi *priv = dev_id;
> > u8 stat;
> >
> > - stat = ioread8(priv->base + NPCM_PSPI_STAT);
> > -
> > if (!priv->tx_buf && !priv->rx_buf)
> > return IRQ_NONE;
> >
> > - if (priv->tx_buf) {
> > - if (stat & NPCM_PSPI_STAT_RBF) {
> > - ioread8(NPCM_PSPI_DATA + priv->base);
> > - if (priv->tx_bytes == 0) {
> > - npcm_pspi_disable(priv);
> > - complete(&priv->xfer_done);
> > - return IRQ_HANDLED;
> > - }
> > - }
> > -
> > - if ((stat & NPCM_PSPI_STAT_BSY) == 0)
> > - if (priv->tx_bytes)
> > - npcm_pspi_send(priv);
> > + if (priv->tx_bytes == 0 && priv->rx_bytes == 0) {
> > + npcm_pspi_disable(priv);
> > + complete(&priv->xfer_done);
> > + return IRQ_HANDLED;
> > }
> >
> > - if (priv->rx_buf) {
> > - if (stat & NPCM_PSPI_STAT_RBF) {
> > - if (!priv->rx_bytes)
> > - return IRQ_NONE;
> > -
> > - npcm_pspi_recv(priv);
> > + stat = ioread8(priv->base + NPCM_PSPI_STAT);
> >
> > - if (!priv->rx_bytes) {
> > - npcm_pspi_disable(priv);
> > - complete(&priv->xfer_done);
> > - return IRQ_HANDLED;
> > - }
> > - }
> > + /*
> > + * first we do the read since if we do the write we previous read might
> > + * be lost (indeed low chances)
> > + */
> > + if ((stat & NPCM_PSPI_STAT_RBF) && priv->rx_bytes)
> > + npcm_pspi_recv(priv);
> >
> > - if (((stat & NPCM_PSPI_STAT_BSY) == 0) && !priv->tx_buf)
> > - iowrite8(0x0, NPCM_PSPI_DATA + priv->base);
> > - }
> > + if (((stat & NPCM_PSPI_STAT_BSY) == 0) && priv->tx_bytes)
> > + npcm_pspi_send(priv);
> >
> > return IRQ_HANDLED;
> > }
> > --
> > 2.22.0
> >
--
Regards,
Avi
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH linux dev-5.8 v2 04/11] watchdog: npcm: Add DT restart priority and reset type support
2021-01-11 0:55 ` Joel Stanley
@ 2021-01-11 19:22 ` Tomer Maimon
0 siblings, 0 replies; 20+ messages in thread
From: Tomer Maimon @ 2021-01-11 19:22 UTC (permalink / raw)
To: Joel Stanley; +Cc: Andrew Jeffery, OpenBMC Maillist, Benjamin Fair
[-- Attachment #1: Type: text/plain, Size: 7570 bytes --]
On Mon, 11 Jan 2021 at 02:55, Joel Stanley <joel@jms.id.au> wrote:
> On Tue, 5 Jan 2021 at 13:45, Tomer Maimon <tmaimon77@gmail.com> wrote:
> >
> > Add Device tree restart priority and
> > three reset types support.
> >
> > Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
>
> Can you remind me the history of this change. Was a similar patch
> rejected by mainline?
>
https://www.spinics.net/lists/kernel/msg3425926.html
>
> > ---
> > drivers/watchdog/npcm_wdt.c | 121 +++++++++++++++++++++++++++++++++++-
> > 1 file changed, 119 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/watchdog/npcm_wdt.c b/drivers/watchdog/npcm_wdt.c
> > index 765577f11c8d..bbf27da34834 100644
> > --- a/drivers/watchdog/npcm_wdt.c
> > +++ b/drivers/watchdog/npcm_wdt.c
> > @@ -11,7 +11,24 @@
> > #include <linux/platform_device.h>
> > #include <linux/slab.h>
> > #include <linux/watchdog.h>
> > -
> > +#include <linux/regmap.h>
> > +#include <linux/mfd/syscon.h>
> > +
> > +/* NPCM7xx GCR module */
> > +#define NPCM7XX_RESSR_OFFSET 0x6C
> > +#define NPCM7XX_INTCR2_OFFSET 0x60
> > +
> > +#define NPCM7XX_PORST BIT(31)
> > +#define NPCM7XX_CORST BIT(30)
> > +#define NPCM7XX_WD0RST BIT(29)
> > +#define NPCM7XX_WD1RST BIT(24)
> > +#define NPCM7XX_WD2RST BIT(23)
> > +#define NPCM7XX_SWR1RST BIT(28)
> > +#define NPCM7XX_SWR2RST BIT(27)
> > +#define NPCM7XX_SWR3RST BIT(26)
> > +#define NPCM7XX_SWR4RST BIT(25)
> > +
> > + /* WD register */
> > #define NPCM_WTCR 0x1C
> >
> > #define NPCM_WTCLK (BIT(10) | BIT(11)) /* Clock divider */
> > @@ -43,6 +60,10 @@
> > struct npcm_wdt {
> > struct watchdog_device wdd;
> > void __iomem *reg;
> > + u32 card_reset;
> > + u32 ext1_reset;
> > + u32 ext2_reset;
> > +
> > };
> >
> > static inline struct npcm_wdt *to_npcm_wdt(struct watchdog_device *wdd)
> > @@ -176,14 +197,70 @@ static const struct watchdog_ops npcm_wdt_ops = {
> > .restart = npcm_wdt_restart,
> > };
> >
> > +static void npcm_get_reset_status(struct npcm_wdt *wdt, struct device
> *dev)
> > +{
> > + struct regmap *gcr_regmap;
> > + u32 rstval;
> > +
> > + if (of_device_is_compatible(dev->of_node,
> "nuvoton,npcm750-wdt")) {
> > + gcr_regmap =
> syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr");
>
> This will have the same issues as the ADC with supporting multiple
> families of chip with the same code. I suggest you adjust it to use
> the phandle approach.
>
> Do you mean by having a gcr phandle property in the wdt npcm device tree
node?
>
> > + if (IS_ERR(gcr_regmap)) {
> > + dev_warn(dev, "Failed to find
> nuvoton,npcm750-gcr WD reset status not supported\n");
> > + }
> > +
> > + regmap_read(gcr_regmap, NPCM7XX_RESSR_OFFSET, &rstval);
> > + if (!rstval) {
> > + regmap_read(gcr_regmap, NPCM7XX_INTCR2_OFFSET,
> &rstval);
> > + rstval = ~rstval;
> > + }
> > +
> > + if(rstval & wdt->card_reset)
> > + wdt->wdd.bootstatus |= WDIOF_CARDRESET;
> > + if(rstval & wdt->ext1_reset)
> > + wdt->wdd.bootstatus |= WDIOF_EXTERN1;
> > + if(rstval & wdt->ext2_reset)
> > + wdt->wdd.bootstatus |= WDIOF_EXTERN2;
> > + }
> > +
> > +}
> > +
> > +static u32 npcm_wdt_reset_type(const char *reset_type)
> > +{
> > + if (!strcmp(reset_type, "porst"))
> > + return NPCM7XX_PORST;
> > + else if (!strcmp(reset_type, "corst"))
> > + return NPCM7XX_CORST;
> > + else if (!strcmp(reset_type, "wd0"))
> > + return NPCM7XX_WD0RST;
> > + else if (!strcmp(reset_type, "wd1"))
> > + return NPCM7XX_WD1RST;
> > + else if (!strcmp(reset_type, "wd2"))
> > + return NPCM7XX_WD2RST;
> > + else if (!strcmp(reset_type, "sw1"))
> > + return NPCM7XX_SWR1RST;
> > + else if (!strcmp(reset_type, "sw2"))
> > + return NPCM7XX_SWR2RST;
> > + else if (!strcmp(reset_type, "sw3"))
> > + return NPCM7XX_SWR3RST;
> > + else if (!strcmp(reset_type, "sw4"))
> > + return NPCM7XX_SWR4RST;
> > +
> > + return 0;
> > +}
> > +
> > static int npcm_wdt_probe(struct platform_device *pdev)
> > {
> > struct device *dev = &pdev->dev;
> > + const char *card_reset_type;
> > + const char *ext1_reset_type;
> > + const char *ext2_reset_type;
> > struct npcm_wdt *wdt;
> > + struct resource *res;
> > + u32 priority;
> > int irq;
> > int ret;
> >
> > - wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
> > + wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
> > if (!wdt)
> > return -ENOMEM;
> >
> > @@ -195,6 +272,45 @@ static int npcm_wdt_probe(struct platform_device
> *pdev)
> > if (irq < 0)
> > return irq;
> >
> > + if (of_property_read_u32(pdev->dev.of_node,
> "nuvoton,restart-priority",
> > + &priority))
> > + watchdog_set_restart_priority(&wdt->wdd, 128);
> > + else
> > + watchdog_set_restart_priority(&wdt->wdd, priority);
> > +
> > + ret = of_property_read_string(pdev->dev.of_node,
> > + "nuvoton,card-reset-type",
> > + &card_reset_type);
> > + if (ret)
> > + wdt->card_reset = NPCM7XX_PORST;
> > + else {
> > + wdt->card_reset = npcm_wdt_reset_type(card_reset_type);
> > + if (!wdt->card_reset)
> > + wdt->card_reset = NPCM7XX_PORST;
> > + }
> > +
> > + ret = of_property_read_string(pdev->dev.of_node,
> > + "nuvoton,ext1-reset-type",
> > + &ext1_reset_type);
> > + if (ret)
> > + wdt->ext1_reset = NPCM7XX_WD0RST;
> > + else {
> > + wdt->ext1_reset = npcm_wdt_reset_type(ext1_reset_type);
> > + if (!wdt->ext1_reset)
> > + wdt->ext1_reset = NPCM7XX_WD0RST;
> > + }
> > +
> > + ret = of_property_read_string(pdev->dev.of_node,
> > + "nuvoton,ext2-reset-type",
> > + &ext2_reset_type);
> > + if (ret)
> > + wdt->ext2_reset = NPCM7XX_SWR1RST;
> > + else {
> > + wdt->ext2_reset = npcm_wdt_reset_type(ext2_reset_type);
> > + if (!wdt->ext2_reset)
> > + wdt->ext2_reset = NPCM7XX_SWR1RST;
> > + }
> > +
> > wdt->wdd.info = &npcm_wdt_info;
> > wdt->wdd.ops = &npcm_wdt_ops;
> > wdt->wdd.min_timeout = 1;
> > @@ -213,6 +329,7 @@ static int npcm_wdt_probe(struct platform_device
> *pdev)
> > set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
> > }
> >
> > + npcm_get_reset_status(wdt, dev);
> > ret = devm_request_irq(dev, irq, npcm_wdt_interrupt, 0,
> "watchdog",
> > wdt);
> > if (ret)
> > --
> > 2.22.0
> >
>
[-- Attachment #2: Type: text/html, Size: 10771 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8
2021-01-11 0:37 ` [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Joel Stanley
@ 2021-01-11 19:30 ` Tomer Maimon
0 siblings, 0 replies; 20+ messages in thread
From: Tomer Maimon @ 2021-01-11 19:30 UTC (permalink / raw)
To: Joel Stanley; +Cc: Andrew Jeffery, OpenBMC Maillist, Benjamin Fair
[-- Attachment #1: Type: text/plain, Size: 3708 bytes --]
Hi Joel,
First tahnks a lot for reviewing the patches.
On Mon, 11 Jan 2021 at 02:37, Joel Stanley <joel@jms.id.au> wrote:
> Hi Tomer,
>
> On Tue, 5 Jan 2021 at 13:45, Tomer Maimon <tmaimon77@gmail.com> wrote:
> >
> > In this patch set we will like to align with relevant modifications
> > in Nuvoton OpenBMC Linux kernel 5.4.
>
> Thanks for sending the patches. I can merge them into 5.8, however I
> have a v5.10 branch that I plan on moving to imminently.
>
> >
> > Linux upstream current status:
> > 1. npcm7xx clock driver - adding read only
> > flag to divider clocks, Will be sent to Linux community.
> > 2. Adding NPCM ADC calibration - Will be sent to Linux vanilla,
> > but I am not sure it will be approved.
> > 3. Add DT restart priority and reset type support - sent to Linux
> > community la but havent approved yet.
> > 4. persist configuration to the pin control driver - asked by a
> costumer,
> > didnt sent to Linux community.
>
> Do you plan on sending it?
>
I need you advise on this one, I pretty sure that the pin
cntroller maintainer will refuse to add it
what do you think?
>
> > 5. Add HGPIO pin support to NPCM7xx pinctrl driver - will be sent
> > to Linux community
> > 6. JTAG master driver - will be sent to Linux community once we
> will
> > have BMC folder.
>
What about the JTAG driver? can you add it please? do I need to move it to
soc folder or to leave it in
misc?
>
> As you've noted, I recommend you submit them to mainline ASAP to avoid
> extra handling of patches in the openbmc tree.
>
you right, I will do my best...
>
> Cheers,
>
> Joel
>
> >
> > Changes since version 1:
> > - Address comments from Jonathan Neuschäfer: removing trailing whitespace
> > in NPCM watchdog documentation.
> > - Adding Stanley Chu to NPCM JTAG master driver
> >
> > Tomer Maimon (11):
> > clk: npcm7xx: add read only flag to divider clocks
> > iio: adc: add calibration support to npcm ADC
> > dts: npcm750: add fuse regmap support node
> > watchdog: npcm: Add DT restart priority and reset type support
> > dt-binding: watchdog: Add DT restart priority and reset type
> > pinctrl: npcm7xx: Add HGPIO pin support to NPCM7xx pinctrl driver
> > pinctrl: pinconf: add pin persist configuration
> > pinctrl: npcm7xx: Add pin persist configuration support
> > spi: npcm-pspi: Add full duplex support
> > dt-binding: bmc: add NPCM7XX JTAG master documentation
> > misc: npcm7xx-jtag-master: add NPCM7xx JTAG master driver
> >
> > .../bindings/bmc/npcm7xx-jtag-master.txt | 38 +
> > .../bindings/watchdog/nuvoton,npcm-wdt.txt | 32 +
> > arch/arm/boot/dts/nuvoton-common-npcm7xx.dtsi | 6 +
> > drivers/clk/clk-npcm7xx.c | 70 +-
> > drivers/iio/adc/npcm_adc.c | 191 ++++
> > drivers/misc/Kconfig | 6 +
> > drivers/misc/Makefile | 1 +
> > drivers/misc/npcm7xx-jtag-master.c | 840 ++++++++++++++++++
> > drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c | 130 ++-
> > drivers/pinctrl/pinconf-generic.c | 3 +
> > drivers/spi/spi-npcm-pspi.c | 75 +-
> > drivers/watchdog/npcm_wdt.c | 121 ++-
> > 12 files changed, 1418 insertions(+), 95 deletions(-)
> > create mode 100644
> Documentation/devicetree/bindings/bmc/npcm7xx-jtag-master.txt
> > create mode 100644 drivers/misc/npcm7xx-jtag-master.c
> >
> > --
> > 2.22.0
> >
>
cheers,
Tomer
[-- Attachment #2: Type: text/html, Size: 5105 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2021-01-11 19:17 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-05 13:44 [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Tomer Maimon
2021-01-05 13:44 ` [PATCH linux dev-5.8 v2 01/11] clk: npcm7xx: add read only flag to divider clocks Tomer Maimon
2021-01-05 13:44 ` [PATCH linux dev-5.8 v2 02/11] iio: adc: add calibration support to npcm ADC Tomer Maimon
2021-01-11 0:52 ` Joel Stanley
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 03/11] dts: npcm750: add fuse regmap support node Tomer Maimon
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 04/11] watchdog: npcm: Add DT restart priority and reset type support Tomer Maimon
2021-01-11 0:55 ` Joel Stanley
2021-01-11 19:22 ` Tomer Maimon
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 05/11] dt-binding: watchdog: Add DT restart priority and reset type Tomer Maimon
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 06/11] pinctrl: npcm7xx: Add HGPIO pin support to NPCM7xx pinctrl driver Tomer Maimon
2021-01-11 0:56 ` Joel Stanley
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 07/11] pinctrl: pinconf: add pin persist configuration Tomer Maimon
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 08/11] pinctrl: npcm7xx: Add pin persist configuration support Tomer Maimon
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 09/11] spi: npcm-pspi: Add full duplex support Tomer Maimon
2021-01-11 1:04 ` Joel Stanley
2021-01-11 10:58 ` Avi Fishman
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 10/11] dt-binding: bmc: add NPCM7XX JTAG master documentation Tomer Maimon
2021-01-05 13:45 ` [PATCH linux dev-5.8 v2 11/11] misc: npcm7xx-jtag-master: add NPCM7xx JTAG master driver Tomer Maimon
2021-01-11 0:37 ` [PATCH linux dev-5.8 v2 00/11] Add NPCM7xx patches to dev-5.8 Joel Stanley
2021-01-11 19:30 ` Tomer Maimon
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.