Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Broadcom BCM63xx Processor Monitor Bus shared routines (SMP and reset)
0004  *
0005  * Copyright (C) 2015, Broadcom Corporation
0006  * Author: Florian Fainelli <f.fainelli@gmail.com>
0007  */
0008 #ifndef __BCM63XX_PMB_H
0009 #define __BCM63XX_PMB_H
0010 
0011 #include <linux/io.h>
0012 #include <linux/types.h>
0013 #include <linux/delay.h>
0014 #include <linux/err.h>
0015 
0016 /* PMB Master controller register */
0017 #define PMB_CTRL        0x00
0018 #define  PMC_PMBM_START     (1 << 31)
0019 #define  PMC_PMBM_TIMEOUT   (1 << 30)
0020 #define  PMC_PMBM_SLAVE_ERR (1 << 29)
0021 #define  PMC_PMBM_BUSY      (1 << 28)
0022 #define  PMC_PMBM_READ      (0 << 20)
0023 #define  PMC_PMBM_WRITE     (1 << 20)
0024 #define PMB_WR_DATA     0x04
0025 #define PMB_TIMEOUT     0x08
0026 #define PMB_RD_DATA     0x0C
0027 
0028 #define PMB_BUS_ID_SHIFT    8
0029 
0030 /* Perform the low-level PMB master operation, shared between reads and
0031  * writes.
0032  */
0033 static inline int __bpcm_do_op(void __iomem *master, unsigned int addr,
0034                    u32 off, u32 op)
0035 {
0036     unsigned int timeout = 1000;
0037     u32 cmd;
0038 
0039     cmd = (PMC_PMBM_START | op | (addr & 0xff) << 12 | off);
0040     writel(cmd, master + PMB_CTRL);
0041     do {
0042         cmd = readl(master + PMB_CTRL);
0043         if (!(cmd & PMC_PMBM_START))
0044             return 0;
0045 
0046         if (cmd & PMC_PMBM_SLAVE_ERR)
0047             return -EIO;
0048 
0049         if (cmd & PMC_PMBM_TIMEOUT)
0050             return -ETIMEDOUT;
0051 
0052         udelay(1);
0053     } while (timeout-- > 0);
0054 
0055     return -ETIMEDOUT;
0056 }
0057 
0058 static inline int bpcm_rd(void __iomem *master, unsigned int addr,
0059               u32 off, u32 *val)
0060 {
0061     int ret = 0;
0062 
0063     ret = __bpcm_do_op(master, addr, off >> 2, PMC_PMBM_READ);
0064     *val = readl(master + PMB_RD_DATA);
0065 
0066     return ret;
0067 }
0068 
0069 static inline int bpcm_wr(void __iomem *master, unsigned int addr,
0070               u32 off, u32 val)
0071 {
0072     int ret = 0;
0073 
0074     writel(val, master + PMB_WR_DATA);
0075     ret = __bpcm_do_op(master, addr, off >> 2, PMC_PMBM_WRITE);
0076 
0077     return ret;
0078 }
0079 
0080 #endif /* __BCM63XX_PMB_H */