1  /* SPDX-License-Identifier: GPL-2.0-only */
2  /*
3   * Broadcom BCM63xx Processor Monitor Bus shared routines (SMP and reset)
4   *
5   * Copyright (C) 2015, Broadcom Corporation
6   * Author: Florian Fainelli <f.fainelli@gmail.com>
7   */
8  #ifndef __BCM63XX_PMB_H
9  #define __BCM63XX_PMB_H
10  
11  #include <linux/io.h>
12  #include <linux/types.h>
13  #include <linux/delay.h>
14  #include <linux/err.h>
15  
16  /* PMB Master controller register */
17  #define PMB_CTRL		0x00
18  #define  PMC_PMBM_START		(1 << 31)
19  #define  PMC_PMBM_TIMEOUT	(1 << 30)
20  #define  PMC_PMBM_SLAVE_ERR	(1 << 29)
21  #define  PMC_PMBM_BUSY		(1 << 28)
22  #define  PMC_PMBM_READ		(0 << 20)
23  #define  PMC_PMBM_WRITE		(1 << 20)
24  #define PMB_WR_DATA		0x04
25  #define PMB_TIMEOUT		0x08
26  #define PMB_RD_DATA		0x0C
27  
28  #define PMB_BUS_ID_SHIFT	8
29  
30  /* Perform the low-level PMB master operation, shared between reads and
31   * writes.
32   */
__bpcm_do_op(void __iomem * master,unsigned int addr,u32 off,u32 op)33  static inline int __bpcm_do_op(void __iomem *master, unsigned int addr,
34  			       u32 off, u32 op)
35  {
36  	unsigned int timeout = 1000;
37  	u32 cmd;
38  
39  	cmd = (PMC_PMBM_START | op | (addr & 0xff) << 12 | off);
40  	writel(cmd, master + PMB_CTRL);
41  	do {
42  		cmd = readl(master + PMB_CTRL);
43  		if (!(cmd & PMC_PMBM_START))
44  			return 0;
45  
46  		if (cmd & PMC_PMBM_SLAVE_ERR)
47  			return -EIO;
48  
49  		if (cmd & PMC_PMBM_TIMEOUT)
50  			return -ETIMEDOUT;
51  
52  		udelay(1);
53  	} while (timeout-- > 0);
54  
55  	return -ETIMEDOUT;
56  }
57  
bpcm_rd(void __iomem * master,unsigned int addr,u32 off,u32 * val)58  static inline int bpcm_rd(void __iomem *master, unsigned int addr,
59  			  u32 off, u32 *val)
60  {
61  	int ret = 0;
62  
63  	ret = __bpcm_do_op(master, addr, off >> 2, PMC_PMBM_READ);
64  	*val = readl(master + PMB_RD_DATA);
65  
66  	return ret;
67  }
68  
bpcm_wr(void __iomem * master,unsigned int addr,u32 off,u32 val)69  static inline int bpcm_wr(void __iomem *master, unsigned int addr,
70  			  u32 off, u32 val)
71  {
72  	int ret = 0;
73  
74  	writel(val, master + PMB_WR_DATA);
75  	ret = __bpcm_do_op(master, addr, off >> 2, PMC_PMBM_WRITE);
76  
77  	return ret;
78  }
79  
80  #endif /* __BCM63XX_PMB_H */
81