Commit | Line | Data |
---|---|---|
6e844b03 FF |
1 | /* |
2 | * Broadcom BCM63xx Processor Monitor Bus shared routines (SMP and reset) | |
3 | * | |
4 | * Copyright (C) 2015, Broadcom Corporation | |
5 | * Author: Florian Fainelli <f.fainelli@gmail.com> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License as | |
9 | * published by the Free Software Foundation version 2. | |
10 | * | |
11 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | |
12 | * kind, whether express or implied; without even the implied warranty | |
13 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | */ | |
16 | #ifndef __BCM63XX_PMB_H | |
17 | #define __BCM63XX_PMB_H | |
18 | ||
19 | #include <linux/io.h> | |
20 | #include <linux/types.h> | |
21 | #include <linux/delay.h> | |
22 | #include <linux/err.h> | |
23 | ||
24 | /* PMB Master controller register */ | |
25 | #define PMB_CTRL 0x00 | |
26 | #define PMC_PMBM_START (1 << 31) | |
27 | #define PMC_PMBM_TIMEOUT (1 << 30) | |
28 | #define PMC_PMBM_SLAVE_ERR (1 << 29) | |
29 | #define PMC_PMBM_BUSY (1 << 28) | |
30 | #define PMC_PMBM_READ (0 << 20) | |
31 | #define PMC_PMBM_WRITE (1 << 20) | |
32 | #define PMB_WR_DATA 0x04 | |
33 | #define PMB_TIMEOUT 0x08 | |
34 | #define PMB_RD_DATA 0x0C | |
35 | ||
36 | #define PMB_BUS_ID_SHIFT 8 | |
37 | ||
38 | /* Perform the low-level PMB master operation, shared between reads and | |
39 | * writes. | |
40 | */ | |
41 | static inline int __bpcm_do_op(void __iomem *master, unsigned int addr, | |
42 | u32 off, u32 op) | |
43 | { | |
44 | unsigned int timeout = 1000; | |
45 | u32 cmd; | |
46 | ||
47 | cmd = (PMC_PMBM_START | op | (addr & 0xff) << 12 | off); | |
48 | writel(cmd, master + PMB_CTRL); | |
49 | do { | |
50 | cmd = readl(master + PMB_CTRL); | |
51 | if (!(cmd & PMC_PMBM_START)) | |
52 | return 0; | |
53 | ||
54 | if (cmd & PMC_PMBM_SLAVE_ERR) | |
55 | return -EIO; | |
56 | ||
57 | if (cmd & PMC_PMBM_TIMEOUT) | |
58 | return -ETIMEDOUT; | |
59 | ||
60 | udelay(1); | |
61 | } while (timeout-- > 0); | |
62 | ||
63 | return -ETIMEDOUT; | |
64 | } | |
65 | ||
66 | static inline int bpcm_rd(void __iomem *master, unsigned int addr, | |
67 | u32 off, u32 *val) | |
68 | { | |
69 | int ret = 0; | |
70 | ||
71 | ret = __bpcm_do_op(master, addr, off >> 2, PMC_PMBM_READ); | |
72 | *val = readl(master + PMB_RD_DATA); | |
73 | ||
74 | return ret; | |
75 | } | |
76 | ||
77 | static inline int bpcm_wr(void __iomem *master, unsigned int addr, | |
78 | u32 off, u32 val) | |
79 | { | |
80 | int ret = 0; | |
81 | ||
82 | writel(val, master + PMB_WR_DATA); | |
83 | ret = __bpcm_do_op(master, addr, off >> 2, PMC_PMBM_WRITE); | |
84 | ||
85 | return ret; | |
86 | } | |
87 | ||
88 | #endif /* __BCM63XX_PMB_H */ |