1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2017 Spreadtrum Communications Inc.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/delay.h>
8*4882a593Smuzhiyun #include <linux/hwspinlock.h>
9*4882a593Smuzhiyun #include <linux/init.h>
10*4882a593Smuzhiyun #include <linux/io.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/of.h>
14*4882a593Smuzhiyun #include <linux/of_device.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/reboot.h>
17*4882a593Smuzhiyun #include <linux/spi/spi.h>
18*4882a593Smuzhiyun #include <linux/sizes.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /* Registers definitions for ADI controller */
21*4882a593Smuzhiyun #define REG_ADI_CTRL0 0x4
22*4882a593Smuzhiyun #define REG_ADI_CHN_PRIL 0x8
23*4882a593Smuzhiyun #define REG_ADI_CHN_PRIH 0xc
24*4882a593Smuzhiyun #define REG_ADI_INT_EN 0x10
25*4882a593Smuzhiyun #define REG_ADI_INT_RAW 0x14
26*4882a593Smuzhiyun #define REG_ADI_INT_MASK 0x18
27*4882a593Smuzhiyun #define REG_ADI_INT_CLR 0x1c
28*4882a593Smuzhiyun #define REG_ADI_GSSI_CFG0 0x20
29*4882a593Smuzhiyun #define REG_ADI_GSSI_CFG1 0x24
30*4882a593Smuzhiyun #define REG_ADI_RD_CMD 0x28
31*4882a593Smuzhiyun #define REG_ADI_RD_DATA 0x2c
32*4882a593Smuzhiyun #define REG_ADI_ARM_FIFO_STS 0x30
33*4882a593Smuzhiyun #define REG_ADI_STS 0x34
34*4882a593Smuzhiyun #define REG_ADI_EVT_FIFO_STS 0x38
35*4882a593Smuzhiyun #define REG_ADI_ARM_CMD_STS 0x3c
36*4882a593Smuzhiyun #define REG_ADI_CHN_EN 0x40
37*4882a593Smuzhiyun #define REG_ADI_CHN_ADDR(id) (0x44 + (id - 2) * 4)
38*4882a593Smuzhiyun #define REG_ADI_CHN_EN1 0x20c
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun /* Bits definitions for register REG_ADI_GSSI_CFG0 */
41*4882a593Smuzhiyun #define BIT_CLK_ALL_ON BIT(30)
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /* Bits definitions for register REG_ADI_RD_DATA */
44*4882a593Smuzhiyun #define BIT_RD_CMD_BUSY BIT(31)
45*4882a593Smuzhiyun #define RD_ADDR_SHIFT 16
46*4882a593Smuzhiyun #define RD_VALUE_MASK GENMASK(15, 0)
47*4882a593Smuzhiyun #define RD_ADDR_MASK GENMASK(30, 16)
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun /* Bits definitions for register REG_ADI_ARM_FIFO_STS */
50*4882a593Smuzhiyun #define BIT_FIFO_FULL BIT(11)
51*4882a593Smuzhiyun #define BIT_FIFO_EMPTY BIT(10)
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun /*
54*4882a593Smuzhiyun * ADI slave devices include RTC, ADC, regulator, charger, thermal and so on.
55*4882a593Smuzhiyun * The slave devices address offset is always 0x8000 and size is 4K.
56*4882a593Smuzhiyun */
57*4882a593Smuzhiyun #define ADI_SLAVE_ADDR_SIZE SZ_4K
58*4882a593Smuzhiyun #define ADI_SLAVE_OFFSET 0x8000
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /* Timeout (ms) for the trylock of hardware spinlocks */
61*4882a593Smuzhiyun #define ADI_HWSPINLOCK_TIMEOUT 5000
62*4882a593Smuzhiyun /*
63*4882a593Smuzhiyun * ADI controller has 50 channels including 2 software channels
64*4882a593Smuzhiyun * and 48 hardware channels.
65*4882a593Smuzhiyun */
66*4882a593Smuzhiyun #define ADI_HW_CHNS 50
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun #define ADI_FIFO_DRAIN_TIMEOUT 1000
69*4882a593Smuzhiyun #define ADI_READ_TIMEOUT 2000
70*4882a593Smuzhiyun #define REG_ADDR_LOW_MASK GENMASK(11, 0)
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun /* Registers definitions for PMIC watchdog controller */
73*4882a593Smuzhiyun #define REG_WDG_LOAD_LOW 0x80
74*4882a593Smuzhiyun #define REG_WDG_LOAD_HIGH 0x84
75*4882a593Smuzhiyun #define REG_WDG_CTRL 0x88
76*4882a593Smuzhiyun #define REG_WDG_LOCK 0xa0
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /* Bits definitions for register REG_WDG_CTRL */
79*4882a593Smuzhiyun #define BIT_WDG_RUN BIT(1)
80*4882a593Smuzhiyun #define BIT_WDG_NEW BIT(2)
81*4882a593Smuzhiyun #define BIT_WDG_RST BIT(3)
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /* Registers definitions for PMIC */
84*4882a593Smuzhiyun #define PMIC_RST_STATUS 0xee8
85*4882a593Smuzhiyun #define PMIC_MODULE_EN 0xc08
86*4882a593Smuzhiyun #define PMIC_CLK_EN 0xc18
87*4882a593Smuzhiyun #define BIT_WDG_EN BIT(2)
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /* Definition of PMIC reset status register */
90*4882a593Smuzhiyun #define HWRST_STATUS_SECURITY 0x02
91*4882a593Smuzhiyun #define HWRST_STATUS_RECOVERY 0x20
92*4882a593Smuzhiyun #define HWRST_STATUS_NORMAL 0x40
93*4882a593Smuzhiyun #define HWRST_STATUS_ALARM 0x50
94*4882a593Smuzhiyun #define HWRST_STATUS_SLEEP 0x60
95*4882a593Smuzhiyun #define HWRST_STATUS_FASTBOOT 0x30
96*4882a593Smuzhiyun #define HWRST_STATUS_SPECIAL 0x70
97*4882a593Smuzhiyun #define HWRST_STATUS_PANIC 0x80
98*4882a593Smuzhiyun #define HWRST_STATUS_CFTREBOOT 0x90
99*4882a593Smuzhiyun #define HWRST_STATUS_AUTODLOADER 0xa0
100*4882a593Smuzhiyun #define HWRST_STATUS_IQMODE 0xb0
101*4882a593Smuzhiyun #define HWRST_STATUS_SPRDISK 0xc0
102*4882a593Smuzhiyun #define HWRST_STATUS_FACTORYTEST 0xe0
103*4882a593Smuzhiyun #define HWRST_STATUS_WATCHDOG 0xf0
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun /* Use default timeout 50 ms that converts to watchdog values */
106*4882a593Smuzhiyun #define WDG_LOAD_VAL ((50 * 32768) / 1000)
107*4882a593Smuzhiyun #define WDG_LOAD_MASK GENMASK(15, 0)
108*4882a593Smuzhiyun #define WDG_UNLOCK_KEY 0xe551
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun struct sprd_adi {
111*4882a593Smuzhiyun struct spi_controller *ctlr;
112*4882a593Smuzhiyun struct device *dev;
113*4882a593Smuzhiyun void __iomem *base;
114*4882a593Smuzhiyun struct hwspinlock *hwlock;
115*4882a593Smuzhiyun unsigned long slave_vbase;
116*4882a593Smuzhiyun unsigned long slave_pbase;
117*4882a593Smuzhiyun struct notifier_block restart_handler;
118*4882a593Smuzhiyun };
119*4882a593Smuzhiyun
sprd_adi_check_paddr(struct sprd_adi * sadi,u32 paddr)120*4882a593Smuzhiyun static int sprd_adi_check_paddr(struct sprd_adi *sadi, u32 paddr)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun if (paddr < sadi->slave_pbase || paddr >
123*4882a593Smuzhiyun (sadi->slave_pbase + ADI_SLAVE_ADDR_SIZE)) {
124*4882a593Smuzhiyun dev_err(sadi->dev,
125*4882a593Smuzhiyun "slave physical address is incorrect, addr = 0x%x\n",
126*4882a593Smuzhiyun paddr);
127*4882a593Smuzhiyun return -EINVAL;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun return 0;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
sprd_adi_to_vaddr(struct sprd_adi * sadi,u32 paddr)133*4882a593Smuzhiyun static unsigned long sprd_adi_to_vaddr(struct sprd_adi *sadi, u32 paddr)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun return (paddr - sadi->slave_pbase + sadi->slave_vbase);
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
sprd_adi_drain_fifo(struct sprd_adi * sadi)138*4882a593Smuzhiyun static int sprd_adi_drain_fifo(struct sprd_adi *sadi)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun u32 timeout = ADI_FIFO_DRAIN_TIMEOUT;
141*4882a593Smuzhiyun u32 sts;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun do {
144*4882a593Smuzhiyun sts = readl_relaxed(sadi->base + REG_ADI_ARM_FIFO_STS);
145*4882a593Smuzhiyun if (sts & BIT_FIFO_EMPTY)
146*4882a593Smuzhiyun break;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun cpu_relax();
149*4882a593Smuzhiyun } while (--timeout);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun if (timeout == 0) {
152*4882a593Smuzhiyun dev_err(sadi->dev, "drain write fifo timeout\n");
153*4882a593Smuzhiyun return -EBUSY;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun return 0;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
sprd_adi_fifo_is_full(struct sprd_adi * sadi)159*4882a593Smuzhiyun static int sprd_adi_fifo_is_full(struct sprd_adi *sadi)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun return readl_relaxed(sadi->base + REG_ADI_ARM_FIFO_STS) & BIT_FIFO_FULL;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
sprd_adi_read(struct sprd_adi * sadi,u32 reg_paddr,u32 * read_val)164*4882a593Smuzhiyun static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun int read_timeout = ADI_READ_TIMEOUT;
167*4882a593Smuzhiyun unsigned long flags;
168*4882a593Smuzhiyun u32 val, rd_addr;
169*4882a593Smuzhiyun int ret = 0;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun if (sadi->hwlock) {
172*4882a593Smuzhiyun ret = hwspin_lock_timeout_irqsave(sadi->hwlock,
173*4882a593Smuzhiyun ADI_HWSPINLOCK_TIMEOUT,
174*4882a593Smuzhiyun &flags);
175*4882a593Smuzhiyun if (ret) {
176*4882a593Smuzhiyun dev_err(sadi->dev, "get the hw lock failed\n");
177*4882a593Smuzhiyun return ret;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun /*
182*4882a593Smuzhiyun * Set the physical register address need to read into RD_CMD register,
183*4882a593Smuzhiyun * then ADI controller will start to transfer automatically.
184*4882a593Smuzhiyun */
185*4882a593Smuzhiyun writel_relaxed(reg_paddr, sadi->base + REG_ADI_RD_CMD);
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun /*
188*4882a593Smuzhiyun * Wait read operation complete, the BIT_RD_CMD_BUSY will be set
189*4882a593Smuzhiyun * simultaneously when writing read command to register, and the
190*4882a593Smuzhiyun * BIT_RD_CMD_BUSY will be cleared after the read operation is
191*4882a593Smuzhiyun * completed.
192*4882a593Smuzhiyun */
193*4882a593Smuzhiyun do {
194*4882a593Smuzhiyun val = readl_relaxed(sadi->base + REG_ADI_RD_DATA);
195*4882a593Smuzhiyun if (!(val & BIT_RD_CMD_BUSY))
196*4882a593Smuzhiyun break;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun cpu_relax();
199*4882a593Smuzhiyun } while (--read_timeout);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun if (read_timeout == 0) {
202*4882a593Smuzhiyun dev_err(sadi->dev, "ADI read timeout\n");
203*4882a593Smuzhiyun ret = -EBUSY;
204*4882a593Smuzhiyun goto out;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun /*
208*4882a593Smuzhiyun * The return value includes data and read register address, from bit 0
209*4882a593Smuzhiyun * to bit 15 are data, and from bit 16 to bit 30 are read register
210*4882a593Smuzhiyun * address. Then we can check the returned register address to validate
211*4882a593Smuzhiyun * data.
212*4882a593Smuzhiyun */
213*4882a593Smuzhiyun rd_addr = (val & RD_ADDR_MASK ) >> RD_ADDR_SHIFT;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun if (rd_addr != (reg_paddr & REG_ADDR_LOW_MASK)) {
216*4882a593Smuzhiyun dev_err(sadi->dev, "read error, reg addr = 0x%x, val = 0x%x\n",
217*4882a593Smuzhiyun reg_paddr, val);
218*4882a593Smuzhiyun ret = -EIO;
219*4882a593Smuzhiyun goto out;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun *read_val = val & RD_VALUE_MASK;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun out:
225*4882a593Smuzhiyun if (sadi->hwlock)
226*4882a593Smuzhiyun hwspin_unlock_irqrestore(sadi->hwlock, &flags);
227*4882a593Smuzhiyun return ret;
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
sprd_adi_write(struct sprd_adi * sadi,u32 reg_paddr,u32 val)230*4882a593Smuzhiyun static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun unsigned long reg = sprd_adi_to_vaddr(sadi, reg_paddr);
233*4882a593Smuzhiyun u32 timeout = ADI_FIFO_DRAIN_TIMEOUT;
234*4882a593Smuzhiyun unsigned long flags;
235*4882a593Smuzhiyun int ret;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun if (sadi->hwlock) {
238*4882a593Smuzhiyun ret = hwspin_lock_timeout_irqsave(sadi->hwlock,
239*4882a593Smuzhiyun ADI_HWSPINLOCK_TIMEOUT,
240*4882a593Smuzhiyun &flags);
241*4882a593Smuzhiyun if (ret) {
242*4882a593Smuzhiyun dev_err(sadi->dev, "get the hw lock failed\n");
243*4882a593Smuzhiyun return ret;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun ret = sprd_adi_drain_fifo(sadi);
248*4882a593Smuzhiyun if (ret < 0)
249*4882a593Smuzhiyun goto out;
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun /*
252*4882a593Smuzhiyun * we should wait for write fifo is empty before writing data to PMIC
253*4882a593Smuzhiyun * registers.
254*4882a593Smuzhiyun */
255*4882a593Smuzhiyun do {
256*4882a593Smuzhiyun if (!sprd_adi_fifo_is_full(sadi)) {
257*4882a593Smuzhiyun writel_relaxed(val, (void __iomem *)reg);
258*4882a593Smuzhiyun break;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun cpu_relax();
262*4882a593Smuzhiyun } while (--timeout);
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun if (timeout == 0) {
265*4882a593Smuzhiyun dev_err(sadi->dev, "write fifo is full\n");
266*4882a593Smuzhiyun ret = -EBUSY;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun out:
270*4882a593Smuzhiyun if (sadi->hwlock)
271*4882a593Smuzhiyun hwspin_unlock_irqrestore(sadi->hwlock, &flags);
272*4882a593Smuzhiyun return ret;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
sprd_adi_transfer_one(struct spi_controller * ctlr,struct spi_device * spi_dev,struct spi_transfer * t)275*4882a593Smuzhiyun static int sprd_adi_transfer_one(struct spi_controller *ctlr,
276*4882a593Smuzhiyun struct spi_device *spi_dev,
277*4882a593Smuzhiyun struct spi_transfer *t)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun struct sprd_adi *sadi = spi_controller_get_devdata(ctlr);
280*4882a593Smuzhiyun u32 phy_reg, val;
281*4882a593Smuzhiyun int ret;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun if (t->rx_buf) {
284*4882a593Smuzhiyun phy_reg = *(u32 *)t->rx_buf + sadi->slave_pbase;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun ret = sprd_adi_check_paddr(sadi, phy_reg);
287*4882a593Smuzhiyun if (ret)
288*4882a593Smuzhiyun return ret;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun ret = sprd_adi_read(sadi, phy_reg, &val);
291*4882a593Smuzhiyun if (ret)
292*4882a593Smuzhiyun return ret;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun *(u32 *)t->rx_buf = val;
295*4882a593Smuzhiyun } else if (t->tx_buf) {
296*4882a593Smuzhiyun u32 *p = (u32 *)t->tx_buf;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun /*
299*4882a593Smuzhiyun * Get the physical register address need to write and convert
300*4882a593Smuzhiyun * the physical address to virtual address. Since we need
301*4882a593Smuzhiyun * virtual register address to write.
302*4882a593Smuzhiyun */
303*4882a593Smuzhiyun phy_reg = *p++ + sadi->slave_pbase;
304*4882a593Smuzhiyun ret = sprd_adi_check_paddr(sadi, phy_reg);
305*4882a593Smuzhiyun if (ret)
306*4882a593Smuzhiyun return ret;
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun val = *p;
309*4882a593Smuzhiyun ret = sprd_adi_write(sadi, phy_reg, val);
310*4882a593Smuzhiyun if (ret)
311*4882a593Smuzhiyun return ret;
312*4882a593Smuzhiyun } else {
313*4882a593Smuzhiyun dev_err(sadi->dev, "no buffer for transfer\n");
314*4882a593Smuzhiyun return -EINVAL;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun return 0;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
sprd_adi_set_wdt_rst_mode(struct sprd_adi * sadi)320*4882a593Smuzhiyun static void sprd_adi_set_wdt_rst_mode(struct sprd_adi *sadi)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SPRD_WATCHDOG)
323*4882a593Smuzhiyun u32 val;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun /* Set default watchdog reboot mode */
326*4882a593Smuzhiyun sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val);
327*4882a593Smuzhiyun val |= HWRST_STATUS_WATCHDOG;
328*4882a593Smuzhiyun sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val);
329*4882a593Smuzhiyun #endif
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun
sprd_adi_restart_handler(struct notifier_block * this,unsigned long mode,void * cmd)332*4882a593Smuzhiyun static int sprd_adi_restart_handler(struct notifier_block *this,
333*4882a593Smuzhiyun unsigned long mode, void *cmd)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun struct sprd_adi *sadi = container_of(this, struct sprd_adi,
336*4882a593Smuzhiyun restart_handler);
337*4882a593Smuzhiyun u32 val, reboot_mode = 0;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun if (!cmd)
340*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_NORMAL;
341*4882a593Smuzhiyun else if (!strncmp(cmd, "recovery", 8))
342*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_RECOVERY;
343*4882a593Smuzhiyun else if (!strncmp(cmd, "alarm", 5))
344*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_ALARM;
345*4882a593Smuzhiyun else if (!strncmp(cmd, "fastsleep", 9))
346*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_SLEEP;
347*4882a593Smuzhiyun else if (!strncmp(cmd, "bootloader", 10))
348*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_FASTBOOT;
349*4882a593Smuzhiyun else if (!strncmp(cmd, "panic", 5))
350*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_PANIC;
351*4882a593Smuzhiyun else if (!strncmp(cmd, "special", 7))
352*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_SPECIAL;
353*4882a593Smuzhiyun else if (!strncmp(cmd, "cftreboot", 9))
354*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_CFTREBOOT;
355*4882a593Smuzhiyun else if (!strncmp(cmd, "autodloader", 11))
356*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_AUTODLOADER;
357*4882a593Smuzhiyun else if (!strncmp(cmd, "iqmode", 6))
358*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_IQMODE;
359*4882a593Smuzhiyun else if (!strncmp(cmd, "sprdisk", 7))
360*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_SPRDISK;
361*4882a593Smuzhiyun else if (!strncmp(cmd, "tospanic", 8))
362*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_SECURITY;
363*4882a593Smuzhiyun else if (!strncmp(cmd, "factorytest", 11))
364*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_FACTORYTEST;
365*4882a593Smuzhiyun else
366*4882a593Smuzhiyun reboot_mode = HWRST_STATUS_NORMAL;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /* Record the reboot mode */
369*4882a593Smuzhiyun sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val);
370*4882a593Smuzhiyun val &= ~HWRST_STATUS_WATCHDOG;
371*4882a593Smuzhiyun val |= reboot_mode;
372*4882a593Smuzhiyun sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val);
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun /* Enable the interface clock of the watchdog */
375*4882a593Smuzhiyun sprd_adi_read(sadi, sadi->slave_pbase + PMIC_MODULE_EN, &val);
376*4882a593Smuzhiyun val |= BIT_WDG_EN;
377*4882a593Smuzhiyun sprd_adi_write(sadi, sadi->slave_pbase + PMIC_MODULE_EN, val);
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun /* Enable the work clock of the watchdog */
380*4882a593Smuzhiyun sprd_adi_read(sadi, sadi->slave_pbase + PMIC_CLK_EN, &val);
381*4882a593Smuzhiyun val |= BIT_WDG_EN;
382*4882a593Smuzhiyun sprd_adi_write(sadi, sadi->slave_pbase + PMIC_CLK_EN, val);
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun /* Unlock the watchdog */
385*4882a593Smuzhiyun sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOCK, WDG_UNLOCK_KEY);
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun sprd_adi_read(sadi, sadi->slave_pbase + REG_WDG_CTRL, &val);
388*4882a593Smuzhiyun val |= BIT_WDG_NEW;
389*4882a593Smuzhiyun sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_CTRL, val);
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /* Load the watchdog timeout value, 50ms is always enough. */
392*4882a593Smuzhiyun sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_HIGH, 0);
393*4882a593Smuzhiyun sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_LOW,
394*4882a593Smuzhiyun WDG_LOAD_VAL & WDG_LOAD_MASK);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun /* Start the watchdog to reset system */
397*4882a593Smuzhiyun sprd_adi_read(sadi, sadi->slave_pbase + REG_WDG_CTRL, &val);
398*4882a593Smuzhiyun val |= BIT_WDG_RUN | BIT_WDG_RST;
399*4882a593Smuzhiyun sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_CTRL, val);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun /* Lock the watchdog */
402*4882a593Smuzhiyun sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOCK, ~WDG_UNLOCK_KEY);
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun mdelay(1000);
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun dev_emerg(sadi->dev, "Unable to restart system\n");
407*4882a593Smuzhiyun return NOTIFY_DONE;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
sprd_adi_hw_init(struct sprd_adi * sadi)410*4882a593Smuzhiyun static void sprd_adi_hw_init(struct sprd_adi *sadi)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun struct device_node *np = sadi->dev->of_node;
413*4882a593Smuzhiyun int i, size, chn_cnt;
414*4882a593Smuzhiyun const __be32 *list;
415*4882a593Smuzhiyun u32 tmp;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun /* Set all channels as default priority */
418*4882a593Smuzhiyun writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIL);
419*4882a593Smuzhiyun writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIH);
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun /* Set clock auto gate mode */
422*4882a593Smuzhiyun tmp = readl_relaxed(sadi->base + REG_ADI_GSSI_CFG0);
423*4882a593Smuzhiyun tmp &= ~BIT_CLK_ALL_ON;
424*4882a593Smuzhiyun writel_relaxed(tmp, sadi->base + REG_ADI_GSSI_CFG0);
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun /* Set hardware channels setting */
427*4882a593Smuzhiyun list = of_get_property(np, "sprd,hw-channels", &size);
428*4882a593Smuzhiyun if (!list || !size) {
429*4882a593Smuzhiyun dev_info(sadi->dev, "no hw channels setting in node\n");
430*4882a593Smuzhiyun return;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun chn_cnt = size / 8;
434*4882a593Smuzhiyun for (i = 0; i < chn_cnt; i++) {
435*4882a593Smuzhiyun u32 value;
436*4882a593Smuzhiyun u32 chn_id = be32_to_cpu(*list++);
437*4882a593Smuzhiyun u32 chn_config = be32_to_cpu(*list++);
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun /* Channel 0 and 1 are software channels */
440*4882a593Smuzhiyun if (chn_id < 2)
441*4882a593Smuzhiyun continue;
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun writel_relaxed(chn_config, sadi->base +
444*4882a593Smuzhiyun REG_ADI_CHN_ADDR(chn_id));
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun if (chn_id < 32) {
447*4882a593Smuzhiyun value = readl_relaxed(sadi->base + REG_ADI_CHN_EN);
448*4882a593Smuzhiyun value |= BIT(chn_id);
449*4882a593Smuzhiyun writel_relaxed(value, sadi->base + REG_ADI_CHN_EN);
450*4882a593Smuzhiyun } else if (chn_id < ADI_HW_CHNS) {
451*4882a593Smuzhiyun value = readl_relaxed(sadi->base + REG_ADI_CHN_EN1);
452*4882a593Smuzhiyun value |= BIT(chn_id - 32);
453*4882a593Smuzhiyun writel_relaxed(value, sadi->base + REG_ADI_CHN_EN1);
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
sprd_adi_probe(struct platform_device * pdev)458*4882a593Smuzhiyun static int sprd_adi_probe(struct platform_device *pdev)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun struct device_node *np = pdev->dev.of_node;
461*4882a593Smuzhiyun struct spi_controller *ctlr;
462*4882a593Smuzhiyun struct sprd_adi *sadi;
463*4882a593Smuzhiyun struct resource *res;
464*4882a593Smuzhiyun u32 num_chipselect;
465*4882a593Smuzhiyun int ret;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun if (!np) {
468*4882a593Smuzhiyun dev_err(&pdev->dev, "can not find the adi bus node\n");
469*4882a593Smuzhiyun return -ENODEV;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun pdev->id = of_alias_get_id(np, "spi");
473*4882a593Smuzhiyun num_chipselect = of_get_child_count(np);
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun ctlr = spi_alloc_master(&pdev->dev, sizeof(struct sprd_adi));
476*4882a593Smuzhiyun if (!ctlr)
477*4882a593Smuzhiyun return -ENOMEM;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun dev_set_drvdata(&pdev->dev, ctlr);
480*4882a593Smuzhiyun sadi = spi_controller_get_devdata(ctlr);
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
483*4882a593Smuzhiyun sadi->base = devm_ioremap_resource(&pdev->dev, res);
484*4882a593Smuzhiyun if (IS_ERR(sadi->base)) {
485*4882a593Smuzhiyun ret = PTR_ERR(sadi->base);
486*4882a593Smuzhiyun goto put_ctlr;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun sadi->slave_vbase = (unsigned long)sadi->base + ADI_SLAVE_OFFSET;
490*4882a593Smuzhiyun sadi->slave_pbase = res->start + ADI_SLAVE_OFFSET;
491*4882a593Smuzhiyun sadi->ctlr = ctlr;
492*4882a593Smuzhiyun sadi->dev = &pdev->dev;
493*4882a593Smuzhiyun ret = of_hwspin_lock_get_id(np, 0);
494*4882a593Smuzhiyun if (ret > 0 || (IS_ENABLED(CONFIG_HWSPINLOCK) && ret == 0)) {
495*4882a593Smuzhiyun sadi->hwlock =
496*4882a593Smuzhiyun devm_hwspin_lock_request_specific(&pdev->dev, ret);
497*4882a593Smuzhiyun if (!sadi->hwlock) {
498*4882a593Smuzhiyun ret = -ENXIO;
499*4882a593Smuzhiyun goto put_ctlr;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun } else {
502*4882a593Smuzhiyun switch (ret) {
503*4882a593Smuzhiyun case -ENOENT:
504*4882a593Smuzhiyun dev_info(&pdev->dev, "no hardware spinlock supplied\n");
505*4882a593Smuzhiyun break;
506*4882a593Smuzhiyun default:
507*4882a593Smuzhiyun dev_err_probe(&pdev->dev, ret, "failed to find hwlock id\n");
508*4882a593Smuzhiyun goto put_ctlr;
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun sprd_adi_hw_init(sadi);
513*4882a593Smuzhiyun sprd_adi_set_wdt_rst_mode(sadi);
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun ctlr->dev.of_node = pdev->dev.of_node;
516*4882a593Smuzhiyun ctlr->bus_num = pdev->id;
517*4882a593Smuzhiyun ctlr->num_chipselect = num_chipselect;
518*4882a593Smuzhiyun ctlr->flags = SPI_MASTER_HALF_DUPLEX;
519*4882a593Smuzhiyun ctlr->bits_per_word_mask = 0;
520*4882a593Smuzhiyun ctlr->transfer_one = sprd_adi_transfer_one;
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun ret = devm_spi_register_controller(&pdev->dev, ctlr);
523*4882a593Smuzhiyun if (ret) {
524*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to register SPI controller\n");
525*4882a593Smuzhiyun goto put_ctlr;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun sadi->restart_handler.notifier_call = sprd_adi_restart_handler;
529*4882a593Smuzhiyun sadi->restart_handler.priority = 128;
530*4882a593Smuzhiyun ret = register_restart_handler(&sadi->restart_handler);
531*4882a593Smuzhiyun if (ret) {
532*4882a593Smuzhiyun dev_err(&pdev->dev, "can not register restart handler\n");
533*4882a593Smuzhiyun goto put_ctlr;
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun return 0;
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun put_ctlr:
539*4882a593Smuzhiyun spi_controller_put(ctlr);
540*4882a593Smuzhiyun return ret;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
sprd_adi_remove(struct platform_device * pdev)543*4882a593Smuzhiyun static int sprd_adi_remove(struct platform_device *pdev)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun struct spi_controller *ctlr = dev_get_drvdata(&pdev->dev);
546*4882a593Smuzhiyun struct sprd_adi *sadi = spi_controller_get_devdata(ctlr);
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun unregister_restart_handler(&sadi->restart_handler);
549*4882a593Smuzhiyun return 0;
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun static const struct of_device_id sprd_adi_of_match[] = {
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun .compatible = "sprd,sc9860-adi",
555*4882a593Smuzhiyun },
556*4882a593Smuzhiyun { },
557*4882a593Smuzhiyun };
558*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, sprd_adi_of_match);
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun static struct platform_driver sprd_adi_driver = {
561*4882a593Smuzhiyun .driver = {
562*4882a593Smuzhiyun .name = "sprd-adi",
563*4882a593Smuzhiyun .of_match_table = sprd_adi_of_match,
564*4882a593Smuzhiyun },
565*4882a593Smuzhiyun .probe = sprd_adi_probe,
566*4882a593Smuzhiyun .remove = sprd_adi_remove,
567*4882a593Smuzhiyun };
568*4882a593Smuzhiyun module_platform_driver(sprd_adi_driver);
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun MODULE_DESCRIPTION("Spreadtrum ADI Controller Driver");
571*4882a593Smuzhiyun MODULE_AUTHOR("Baolin Wang <Baolin.Wang@spreadtrum.com>");
572*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
573