From f601b2e21a8760457bf57b47e2716ed96a84fc3f Mon Sep 17 00:00:00 2001 From: Sunny Luo Date: Fri, 5 May 2017 20:45:58 +0800 Subject: [PATCH] spicc: add spicc driver for axg PD#142470: add spicc driver for axg and fix spicc-b interrupt number error Change-Id: Ibbda6d8526c4141992fcbe307d6f1e0fbc570cfe Signed-off-by: Sunny Luo --- arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts | 17 ++++++++ arch/arm64/boot/dts/amlogic/axg_pxp.dts | 17 ++++++++ arch/arm64/boot/dts/amlogic/axg_s400.dts | 17 ++++++++ arch/arm64/boot/dts/amlogic/axg_s420.dts | 17 ++++++++ arch/arm64/boot/dts/amlogic/mesonaxg.dtsi | 60 +++++++++++++++++++++++++++ drivers/amlogic/spicc/spicc.c | 59 ++++++++++++++++++++++---- drivers/amlogic/spicc/spicc.h | 13 ++++++ 7 files changed, 192 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts b/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts index b39d03d..9e941b8 100644 --- a/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts @@ -177,3 +177,20 @@ }; /* end of / */ +&spicc_a{ + status = "okay"; + num_chipselect = <1>; + dma_en = <0>; + delay_control = <0x15>; + cs_delay = <10>; + enhance_dlyctl = <0>; +}; + +&spicc_b{ + status = "disabled"; + num_chipselect = <1>; + dma_en = <0>; + delay_control = <0x15>; + cs_delay = <10>; + enhance_dlyctl = <0>; +}; diff --git a/arch/arm64/boot/dts/amlogic/axg_pxp.dts b/arch/arm64/boot/dts/amlogic/axg_pxp.dts index 04cacd4..d9cf3c9 100644 --- a/arch/arm64/boot/dts/amlogic/axg_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/axg_pxp.dts @@ -119,3 +119,20 @@ }; /* end of / */ +&spicc_a{ + status = "disabled"; + num_chipselect = <1>; + dma_en = <0>; + delay_control = <0x15>; + cs_delay = <10>; + enhance_dlyctl = <0>; +}; + +&spicc_b{ + status = "disabled"; + num_chipselect = <1>; + dma_en = <0>; + delay_control = <0x15>; + cs_delay = <10>; + enhance_dlyctl = <0>; +}; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400.dts b/arch/arm64/boot/dts/amlogic/axg_s400.dts index 200c9fb..994e3b4 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400.dts @@ -175,3 +175,20 @@ }; /* end of / */ +&spicc_a{ + status = "disabled"; + num_chipselect = <1>; + dma_en = <0>; + delay_control = <0x15>; + cs_delay = <10>; + enhance_dlyctl = <0>; +}; + +&spicc_b{ + status = "disabled"; + num_chipselect = <1>; + dma_en = <0>; + delay_control = <0x15>; + cs_delay = <10>; + enhance_dlyctl = <0>; +}; diff --git a/arch/arm64/boot/dts/amlogic/axg_s420.dts b/arch/arm64/boot/dts/amlogic/axg_s420.dts index 132213e..c44aa54 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420.dts @@ -114,3 +114,20 @@ }; }; /* end of / */ +&spicc_a{ + status = "disabled"; + num_chipselect = <1>; + dma_en = <0>; + delay_control = <0x15>; + cs_delay = <10>; + enhance_dlyctl = <0>; +}; + +&spicc_b{ + status = "disabled"; + num_chipselect = <1>; + dma_en = <0>; + delay_control = <0x15>; + cs_delay = <10>; + enhance_dlyctl = <0>; +}; diff --git a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi index 9692fd7..bbe842c 100644 --- a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi @@ -334,6 +334,46 @@ /*and you can shoose it in file dt-bindings/pwm/meson.h*/ }; + spicc_a:spicc_a { + compatible = "amlogic, spicc"; + status = "disabled"; + reg = <0x0 0xffd13000 0x0 0x3c>; + clocks = <&clkc CLKID_SPICC0>, + <&clkc CLKID_SPICC_COMP>; + clock-names = "spicc_clk", + "cts_spicc_hclk"; + interrupts = <0 81 1>; + device_id = <0>; + enhance = <1>; + pinctrl-names= "default"; + pinctrl-0=<&spicc_a_pins>; + dma_tx_threshold = <3>; + dma_rx_threshold = <3>; + dma_num_per_read_burst = <3>; + dma_num_per_write_burst = <3>; + ssctl = <0>; + }; + + spicc_b:spicc_b { + compatible = "amlogic, spicc"; + status = "disabled"; + reg = <0x0 0xffd15000 0x0 0x3c>; + clocks = <&clkc CLKID_SPICC1>, + <&clkc CLKID_SPICC_COMP>; + clock-names = "spicc_clk", + "cts_spicc_hclk"; + interrupts = <0 82 1>; + device_id = <1>; + enhance = <1>; + pinctrl-names= "default"; + pinctrl-0=<&spicc_b_pins_X>; + dma_tx_threshold = <3>; + dma_rx_threshold = <3>; + dma_num_per_read_burst = <3>; + dma_num_per_write_burst = <3>; + ssctl = <0>; + }; + i2c_ao: i2c@ff805000{ /*I2C-AO*/ compatible = "amlogic, meson-i2c"; dev_name = "i2c-AO"; @@ -533,6 +573,26 @@ function = "i2c_d"; }; }; + + spicc_a_pins: spicc_a_pins{ + mux { + pins = "GPIOZ_0","GPIOZ_1","GPIOZ_2","GPIOZ_3"; + function = "spi_a"; + }; + }; + spicc_b_pins_A: spicc_b_pins_A{ + mux { + pins="GPIOA_2","GPIOA_3","GPIOA_4","GPIOA_5"; + function = "spi_b"; + }; + }; + spicc_b_pins_X: spicc_b_pins_X{ + mux { + pins = "GPIOX_16","GPIOX_17","GPIOX_18","GPIOX_19"; + function = "spi_b"; + }; + }; + }; /* end of pinctrl_periphs */ &aobus{ diff --git a/drivers/amlogic/spicc/spicc.c b/drivers/amlogic/spicc/spicc.c index 281d28c..be37dc5 100644 --- a/drivers/amlogic/spicc/spicc.c +++ b/drivers/amlogic/spicc/spicc.c @@ -41,7 +41,6 @@ #ifdef CONFIG_SPICC_LOG struct my_log { struct timeval tv; - unsigned int irq_data; unsigned int reg_val[13]; unsigned int param[8]; unsigned int param_count; @@ -71,6 +70,7 @@ struct spicc { int device_id; struct reset_control *rst; struct clk *clk; + struct clk *hclk; void __iomem *regs; struct pinctrl *pinctrl; struct pinctrl_state *pullup; @@ -92,6 +92,7 @@ struct spicc { u8 test_data; unsigned int delay_control; unsigned int cs_delay; + unsigned int enhance_dlyctl; int remain; u8 *txp; u8 *rxp; @@ -158,17 +159,12 @@ static void spicc_log( int comment_id) { struct my_log *log; - struct irq_desc *desc; int i; if (IS_ERR_OR_NULL(spicc->log)) return; log = &spicc->log[spicc->log_count]; log->tv = ktime_to_timeval(ktime_get()); - if (spicc->irq) { - desc = irq_to_desc(spicc->irq); - log->irq_data = desc->irq_data.state_use_accessors; - } for (i = 0; i < ARRAY_SIZE(log->reg_val); i++) log->reg_val[i] = readl(spicc->regs + ((i+2)<<2)); @@ -200,7 +196,6 @@ static void spicc_log_print(struct spicc *spicc) (unsigned int)log->tv.tv_sec, (unsigned int)log->tv.tv_usec, i, log->comment); - pr_info("irq_data=0x%x\n", log->irq_data); p = log->reg_val; for (j = 0; j < ARRAY_SIZE(log->reg_val); j++) if (*p) @@ -297,7 +292,12 @@ static void spicc_set_clk(struct spicc *spicc, int speed) sys_clk_rate = clk_get_rate(spicc->clk); if (spicc_get_flag(spicc, FLAG_ENHANCE)) { - div = (sys_clk_rate/speed)-1; + div = sys_clk_rate/speed; + if (div < 2) + div = 2; + div = (div >> 1) - 1; + if (div > 0xff) + div = 0xff; setb(spicc->regs, ENHANCE_CLK_DIV, div); setb(spicc->regs, ENHANCE_CLK_DIV_SELECT, 1); } else { @@ -612,6 +612,8 @@ static void spicc_hw_init(struct spicc *spicc) setb(mem_base, CS_OEN, 1); setb(mem_base, CS_DELAY, spicc->cs_delay); setb(mem_base, CS_DELAY_EN, 1); + writel(spicc->enhance_dlyctl, + spicc->regs + SPICC_REG_ENHANCE_CNTL1); } /* spicc_enable(spicc, 0); */ } @@ -987,10 +989,27 @@ static int of_spicc_get_data( return PTR_ERR(spicc->regs); } + spicc->rst = devm_reset_control_get(&pdev->dev, "spicc_rst"); + if (IS_ERR_OR_NULL(spicc->rst)) + dev_err(&pdev->dev, "get reset failed\n"); + else + reset_control_deassert(spicc->rst); + spicc->clk = devm_clk_get(&pdev->dev, "spicc_clk"); if (IS_ERR_OR_NULL(spicc->clk)) { dev_err(&pdev->dev, "get clk fail\n"); return PTR_ERR(spicc->clk); + } else { + + } + spicc->hclk = devm_clk_get(&pdev->dev, "cts_spicc_hclk"); + if (IS_ERR_OR_NULL(spicc->hclk)) { + dev_err(&pdev->dev, "get cts_spicc_hclk failed\n"); + } else { + err = of_property_read_u32(np, "enhance_dlyctl", &value); + spicc->enhance_dlyctl = err ? 0 : value; + dev_info(&pdev->dev, "enhance_dlyctl=0x%x\n", + spicc->enhance_dlyctl); } return 0; } @@ -1086,6 +1105,28 @@ static int spicc_remove(struct platform_device *pdev) return 0; } +static int spicc_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct spicc *spicc; + unsigned long flags; + + spicc = (struct spicc *)dev_get_drvdata(&pdev->dev); + spin_lock_irqsave(&spicc->lock, flags); + spin_unlock_irqrestore(&spicc->lock, flags); + return 0; +} + +static int spicc_resume(struct platform_device *pdev) +{ + struct spicc *spicc; + unsigned long flags; + + spicc = (struct spicc *)dev_get_drvdata(&pdev->dev); + spin_lock_irqsave(&spicc->lock, flags); + spin_unlock_irqrestore(&spicc->lock, flags); + return 0; +} + #ifdef CONFIG_OF static const struct of_device_id spicc_of_match[] = { { .compatible = "amlogic, spicc", }, @@ -1098,6 +1139,8 @@ static const struct of_device_id spicc_of_match[] = { static struct platform_driver spicc_driver = { .probe = spicc_probe, .remove = spicc_remove, + .suspend = spicc_suspend, + .resume = spicc_resume, .driver = { .name = "spicc", .of_match_table = spicc_of_match, diff --git a/drivers/amlogic/spicc/spicc.h b/drivers/amlogic/spicc/spicc.h index 51e43d1..0080675 100644 --- a/drivers/amlogic/spicc/spicc.h +++ b/drivers/amlogic/spicc/spicc.h @@ -39,6 +39,7 @@ #define SPICC_REG_LD_RADDR (12<<2) #define SPICC_REG_LD_WADDR (13<<2) #define SPICC_REG_ENHANCE_CNTL (14<<2) +#define SPICC_REG_ENHANCE_CNTL1 (15<<2) #define CON_ENABLE bits_desc(SPICC_REG_CON, 0, 1) #define CON_MODE bits_desc(SPICC_REG_CON, 1, 1) @@ -98,6 +99,18 @@ #define CS_DELAY_EN bits_desc(SPICC_REG_ENHANCE_CNTL, 28, 1) #define MAIN_CLK_AO bits_desc(SPICC_REG_ENHANCE_CNTL, 29, 1) +#define MISO_I_CAPTURE_EN bits_desc(SPICC_REG_ENHANCE_CNTL1, 0, 1) +#define MISO_I_CAPTURE_DELAY bits_desc(SPICC_REG_ENHANCE_CNTL1, 1, 9) +#define MOSI_I_CAPTURE_EN bits_desc(SPICC_REG_ENHANCE_CNTL1, 14, 1) +#define FCLK_EN bits_desc(SPICC_REG_ENHANCE_CNTL1, 15, 1) +#define MOSI_I_DLYCTL_EN bits_desc(SPICC_REG_ENHANCE_CNTL1, 16, 1) +#define MOSI_I_DLYCTL bits_desc(SPICC_REG_ENHANCE_CNTL1, 17, 3) +#define MISO_I_DLYCTL_EN bits_desc(SPICC_REG_ENHANCE_CNTL1, 20, 1) +#define MISO_I_DLYCTL bits_desc(SPICC_REG_ENHANCE_CNTL1, 21, 3) +#define MOSI_O_DLYCTL_EN bits_desc(SPICC_REG_ENHANCE_CNTL1, 24, 1) +#define MOSI_O_DLYCTL bits_desc(SPICC_REG_ENHANCE_CNTL1, 25, 3) +#define MOSI_OEN_DLYCTL_EN bits_desc(SPICC_REG_ENHANCE_CNTL1, 28, 1) +#define MOSI_OEN_DLYCTL bits_desc(SPICC_REG_ENHANCE_CNTL1, 29, 3) struct spicc_platform_data { int device_id; -- 2.7.4