Merge tag 'arm-soc/for-3.19/brcmstb-drivers' of https://github.com/brcm/linux into...
authorArnd Bergmann <arnd@arndb.de>
Thu, 4 Dec 2014 15:44:05 +0000 (16:44 +0100)
committerArnd Bergmann <arnd@arndb.de>
Thu, 4 Dec 2014 15:44:05 +0000 (16:44 +0100)
This pull request contains the following changes to the Broadcom GISB bus
arbiter from Kevin Cernekee:

- Extend brcmstb GISB bus driver to work on MIPS (currently ARM-only) and support
  65nm and 40nm MIPS-based chips such as: BCM7038, BCM7400 and BCM7435

* tag 'arm-soc/for-3.19/brcmstb-drivers' of https://github.com/brcm/linux:
  bus: brcmstb_gisb: Add register offset tables for older chips
  bus: brcmstb_gisb: Look up register offsets in a table
  bus: brcmstb_gisb: Introduce wrapper functions for MMIO accesses
  bus: brcmstb_gisb: Make the driver buildable on MIPS

Conflicts:
drivers/bus/brcmstb_gisb.c

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
1  2 
drivers/bus/brcmstb_gisb.c

  #include <linux/of.h>
  #include <linux/bitops.h>
  
+ #ifdef CONFIG_ARM
  #include <asm/bug.h>
  #include <asm/signal.h>
+ #endif
  
- #define ARB_TIMER                     0x008
- #define ARB_ERR_CAP_CLR                       0x7e4
  #define  ARB_ERR_CAP_CLEAR            (1 << 0)
- #define ARB_ERR_CAP_HI_ADDR           0x7e8
- #define ARB_ERR_CAP_ADDR              0x7ec
- #define ARB_ERR_CAP_DATA              0x7f0
- #define ARB_ERR_CAP_STATUS            0x7f4
  #define  ARB_ERR_CAP_STATUS_TIMEOUT   (1 << 12)
  #define  ARB_ERR_CAP_STATUS_TEA               (1 << 11)
  #define  ARB_ERR_CAP_STATUS_BS_SHIFT  (1 << 2)
  #define  ARB_ERR_CAP_STATUS_BS_MASK   0x3c
  #define  ARB_ERR_CAP_STATUS_WRITE     (1 << 1)
  #define  ARB_ERR_CAP_STATUS_VALID     (1 << 0)
- #define ARB_ERR_CAP_MASTER            0x7f8
+ enum {
+       ARB_TIMER,
+       ARB_ERR_CAP_CLR,
+       ARB_ERR_CAP_HI_ADDR,
+       ARB_ERR_CAP_ADDR,
+       ARB_ERR_CAP_DATA,
+       ARB_ERR_CAP_STATUS,
+       ARB_ERR_CAP_MASTER,
+ };
+ static const int gisb_offsets_bcm7038[] = {
+       [ARB_TIMER]             = 0x00c,
+       [ARB_ERR_CAP_CLR]       = 0x0c4,
+       [ARB_ERR_CAP_HI_ADDR]   = -1,
+       [ARB_ERR_CAP_ADDR]      = 0x0c8,
+       [ARB_ERR_CAP_DATA]      = 0x0cc,
+       [ARB_ERR_CAP_STATUS]    = 0x0d0,
+       [ARB_ERR_CAP_MASTER]    = -1,
+ };
+ static const int gisb_offsets_bcm7400[] = {
+       [ARB_TIMER]             = 0x00c,
+       [ARB_ERR_CAP_CLR]       = 0x0c8,
+       [ARB_ERR_CAP_HI_ADDR]   = -1,
+       [ARB_ERR_CAP_ADDR]      = 0x0cc,
+       [ARB_ERR_CAP_DATA]      = 0x0d0,
+       [ARB_ERR_CAP_STATUS]    = 0x0d4,
+       [ARB_ERR_CAP_MASTER]    = 0x0d8,
+ };
+ static const int gisb_offsets_bcm7435[] = {
+       [ARB_TIMER]             = 0x00c,
+       [ARB_ERR_CAP_CLR]       = 0x168,
+       [ARB_ERR_CAP_HI_ADDR]   = -1,
+       [ARB_ERR_CAP_ADDR]      = 0x16c,
+       [ARB_ERR_CAP_DATA]      = 0x170,
+       [ARB_ERR_CAP_STATUS]    = 0x174,
+       [ARB_ERR_CAP_MASTER]    = 0x178,
+ };
+ static const int gisb_offsets_bcm7445[] = {
+       [ARB_TIMER]             = 0x008,
+       [ARB_ERR_CAP_CLR]       = 0x7e4,
+       [ARB_ERR_CAP_HI_ADDR]   = 0x7e8,
+       [ARB_ERR_CAP_ADDR]      = 0x7ec,
+       [ARB_ERR_CAP_DATA]      = 0x7f0,
+       [ARB_ERR_CAP_STATUS]    = 0x7f4,
+       [ARB_ERR_CAP_MASTER]    = 0x7f8,
+ };
  
  struct brcmstb_gisb_arb_device {
        void __iomem    *base;
+       const int       *gisb_offsets;
        struct mutex    lock;
        struct list_head next;
        u32 valid_mask;
  
  static LIST_HEAD(brcmstb_gisb_arb_device_list);
  
+ static u32 gisb_read(struct brcmstb_gisb_arb_device *gdev, int reg)
+ {
+       int offset = gdev->gisb_offsets[reg];
+       /* return 1 if the hardware doesn't have ARB_ERR_CAP_MASTER */
+       if (offset == -1)
+               return 1;
+       return ioread32(gdev->base + offset);
+ }
+ static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg)
+ {
+       int offset = gdev->gisb_offsets[reg];
+       if (offset == -1)
+               return;
+       iowrite32(val, gdev->base + reg);
+ }
  static ssize_t gisb_arb_get_timeout(struct device *dev,
                                    struct device_attribute *attr,
                                    char *buf)
        u32 timeout;
  
        mutex_lock(&gdev->lock);
-       timeout = ioread32(gdev->base + ARB_TIMER);
+       timeout = gisb_read(gdev, ARB_TIMER);
        mutex_unlock(&gdev->lock);
  
        return sprintf(buf, "%d", timeout);
@@@ -83,7 -149,7 +149,7 @@@ static ssize_t gisb_arb_set_timeout(str
                return -EINVAL;
  
        mutex_lock(&gdev->lock);
-       iowrite32(val, gdev->base + ARB_TIMER);
+       gisb_write(gdev, val, ARB_TIMER);
        mutex_unlock(&gdev->lock);
  
        return count;
@@@ -110,18 -176,18 +176,18 @@@ static int brcmstb_gisb_arb_decode_addr
        const char *m_name;
        char m_fmt[11];
  
-       cap_status = ioread32(gdev->base + ARB_ERR_CAP_STATUS);
+       cap_status = gisb_read(gdev, ARB_ERR_CAP_STATUS);
  
        /* Invalid captured address, bail out */
        if (!(cap_status & ARB_ERR_CAP_STATUS_VALID))
                return 1;
  
        /* Read the address and master */
-       arb_addr = ioread32(gdev->base + ARB_ERR_CAP_ADDR) & 0xffffffff;
+       arb_addr = gisb_read(gdev, ARB_ERR_CAP_ADDR) & 0xffffffff;
  #if (IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT))
-       arb_addr |= (u64)ioread32(gdev->base + ARB_ERR_CAP_HI_ADDR) << 32;
+       arb_addr |= (u64)gisb_read(gdev, ARB_ERR_CAP_HI_ADDR) << 32;
  #endif
-       master = ioread32(gdev->base + ARB_ERR_CAP_MASTER);
+       master = gisb_read(gdev, ARB_ERR_CAP_MASTER);
  
        m_name = brcmstb_gisb_master_to_str(gdev, master);
        if (!m_name) {
                m_name);
  
        /* clear the GISB error */
-       iowrite32(ARB_ERR_CAP_CLEAR, gdev->base + ARB_ERR_CAP_CLR);
+       gisb_write(gdev, ARB_ERR_CAP_CLEAR, ARB_ERR_CAP_CLR);
  
        return 0;
  }
  
+ #ifdef CONFIG_ARM
  static int brcmstb_bus_error_handler(unsigned long addr, unsigned int fsr,
                                     struct pt_regs *regs)
  {
@@@ -165,6 -232,7 +232,7 @@@ void __init brcmstb_hook_fault_code(voi
        hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0,
                        "imprecise external abort");
  }
+ #endif
  
  static irqreturn_t brcmstb_gisb_timeout_handler(int irq, void *dev_id)
  {
@@@ -192,10 -260,20 +260,20 @@@ static struct attribute_group gisb_arb_
        .attrs = gisb_arb_sysfs_attrs,
  };
  
 -static int brcmstb_gisb_arb_probe(struct platform_device *pdev)
+ static const struct of_device_id brcmstb_gisb_arb_of_match[] = {
+       { .compatible = "brcm,gisb-arb",         .data = gisb_offsets_bcm7445 },
+       { .compatible = "brcm,bcm7445-gisb-arb", .data = gisb_offsets_bcm7445 },
+       { .compatible = "brcm,bcm7435-gisb-arb", .data = gisb_offsets_bcm7435 },
+       { .compatible = "brcm,bcm7400-gisb-arb", .data = gisb_offsets_bcm7400 },
+       { .compatible = "brcm,bcm7038-gisb-arb", .data = gisb_offsets_bcm7038 },
+       { },
+ };
 +static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
  {
        struct device_node *dn = pdev->dev.of_node;
        struct brcmstb_gisb_arb_device *gdev;
+       const struct of_device_id *of_id;
        struct resource *r;
        int err, timeout_irq, tea_irq;
        unsigned int num_masters, j = 0;
        if (IS_ERR(gdev->base))
                return PTR_ERR(gdev->base);
  
+       of_id = of_match_node(brcmstb_gisb_arb_of_match, dn);
+       if (!of_id) {
+               pr_err("failed to look up compatible string\n");
+               return -EINVAL;
+       }
+       gdev->gisb_offsets = of_id->data;
        err = devm_request_irq(&pdev->dev, timeout_irq,
                                brcmstb_gisb_timeout_handler, 0, pdev->name,
                                gdev);
        return 0;
  }
  
- static const struct of_device_id brcmstb_gisb_arb_of_match[] = {
-       { .compatible = "brcm,gisb-arb" },
-       { },
- };
  static struct platform_driver brcmstb_gisb_arb_driver = {
 -      .probe  = brcmstb_gisb_arb_probe,
        .driver = {
                .name   = "brcm-gisb-arb",
                .owner  = THIS_MODULE,
  
  static int __init brcm_gisb_driver_init(void)
  {
 -      return platform_driver_register(&brcmstb_gisb_arb_driver);
 +      return platform_driver_probe(&brcmstb_gisb_arb_driver,
 +                                   brcmstb_gisb_arb_probe);
  }
  
  module_init(brcm_gisb_driver_init);