root/arch/sparc/kernel/central.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. clock_board_calc_nslots
  2. clock_board_probe
  3. fhc_probe
  4. sunfire_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* central.c: Central FHC driver for Sunfire/Starfire/Wildfire.
   3  *
   4  * Copyright (C) 1997, 1999, 2008 David S. Miller (davem@davemloft.net)
   5  */
   6 
   7 #include <linux/kernel.h>
   8 #include <linux/types.h>
   9 #include <linux/slab.h>
  10 #include <linux/export.h>
  11 #include <linux/string.h>
  12 #include <linux/init.h>
  13 #include <linux/of_device.h>
  14 #include <linux/platform_device.h>
  15 
  16 #include <asm/fhc.h>
  17 #include <asm/upa.h>
  18 
  19 struct clock_board {
  20         void __iomem            *clock_freq_regs;
  21         void __iomem            *clock_regs;
  22         void __iomem            *clock_ver_reg;
  23         int                     num_slots;
  24         struct resource         leds_resource;
  25         struct platform_device  leds_pdev;
  26 };
  27 
  28 struct fhc {
  29         void __iomem            *pregs;
  30         bool                    central;
  31         bool                    jtag_master;
  32         int                     board_num;
  33         struct resource         leds_resource;
  34         struct platform_device  leds_pdev;
  35 };
  36 
  37 static int clock_board_calc_nslots(struct clock_board *p)
  38 {
  39         u8 reg = upa_readb(p->clock_regs + CLOCK_STAT1) & 0xc0;
  40 
  41         switch (reg) {
  42         case 0x40:
  43                 return 16;
  44 
  45         case 0xc0:
  46                 return 8;
  47 
  48         case 0x80:
  49                 reg = 0;
  50                 if (p->clock_ver_reg)
  51                         reg = upa_readb(p->clock_ver_reg);
  52                 if (reg) {
  53                         if (reg & 0x80)
  54                                 return 4;
  55                         else
  56                                 return 5;
  57                 }
  58                 /* Fallthrough */
  59         default:
  60                 return 4;
  61         }
  62 }
  63 
  64 static int clock_board_probe(struct platform_device *op)
  65 {
  66         struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL);
  67         int err = -ENOMEM;
  68 
  69         if (!p) {
  70                 printk(KERN_ERR "clock_board: Cannot allocate struct clock_board\n");
  71                 goto out;
  72         }
  73 
  74         p->clock_freq_regs = of_ioremap(&op->resource[0], 0,
  75                                         resource_size(&op->resource[0]),
  76                                         "clock_board_freq");
  77         if (!p->clock_freq_regs) {
  78                 printk(KERN_ERR "clock_board: Cannot map clock_freq_regs\n");
  79                 goto out_free;
  80         }
  81 
  82         p->clock_regs = of_ioremap(&op->resource[1], 0,
  83                                    resource_size(&op->resource[1]),
  84                                    "clock_board_regs");
  85         if (!p->clock_regs) {
  86                 printk(KERN_ERR "clock_board: Cannot map clock_regs\n");
  87                 goto out_unmap_clock_freq_regs;
  88         }
  89 
  90         if (op->resource[2].flags) {
  91                 p->clock_ver_reg = of_ioremap(&op->resource[2], 0,
  92                                               resource_size(&op->resource[2]),
  93                                               "clock_ver_reg");
  94                 if (!p->clock_ver_reg) {
  95                         printk(KERN_ERR "clock_board: Cannot map clock_ver_reg\n");
  96                         goto out_unmap_clock_regs;
  97                 }
  98         }
  99 
 100         p->num_slots = clock_board_calc_nslots(p);
 101 
 102         p->leds_resource.start = (unsigned long)
 103                 (p->clock_regs + CLOCK_CTRL);
 104         p->leds_resource.end = p->leds_resource.start;
 105         p->leds_resource.name = "leds";
 106 
 107         p->leds_pdev.name = "sunfire-clockboard-leds";
 108         p->leds_pdev.id = -1;
 109         p->leds_pdev.resource = &p->leds_resource;
 110         p->leds_pdev.num_resources = 1;
 111         p->leds_pdev.dev.parent = &op->dev;
 112 
 113         err = platform_device_register(&p->leds_pdev);
 114         if (err) {
 115                 printk(KERN_ERR "clock_board: Could not register LEDS "
 116                        "platform device\n");
 117                 goto out_unmap_clock_ver_reg;
 118         }
 119 
 120         printk(KERN_INFO "clock_board: Detected %d slot Enterprise system.\n",
 121                p->num_slots);
 122 
 123         err = 0;
 124 out:
 125         return err;
 126 
 127 out_unmap_clock_ver_reg:
 128         if (p->clock_ver_reg)
 129                 of_iounmap(&op->resource[2], p->clock_ver_reg,
 130                            resource_size(&op->resource[2]));
 131 
 132 out_unmap_clock_regs:
 133         of_iounmap(&op->resource[1], p->clock_regs,
 134                    resource_size(&op->resource[1]));
 135 
 136 out_unmap_clock_freq_regs:
 137         of_iounmap(&op->resource[0], p->clock_freq_regs,
 138                    resource_size(&op->resource[0]));
 139 
 140 out_free:
 141         kfree(p);
 142         goto out;
 143 }
 144 
 145 static const struct of_device_id clock_board_match[] = {
 146         {
 147                 .name = "clock-board",
 148         },
 149         {},
 150 };
 151 
 152 static struct platform_driver clock_board_driver = {
 153         .probe          = clock_board_probe,
 154         .driver = {
 155                 .name = "clock_board",
 156                 .of_match_table = clock_board_match,
 157         },
 158 };
 159 
 160 static int fhc_probe(struct platform_device *op)
 161 {
 162         struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL);
 163         int err = -ENOMEM;
 164         u32 reg;
 165 
 166         if (!p) {
 167                 printk(KERN_ERR "fhc: Cannot allocate struct fhc\n");
 168                 goto out;
 169         }
 170 
 171         if (of_node_name_eq(op->dev.of_node->parent, "central"))
 172                 p->central = true;
 173 
 174         p->pregs = of_ioremap(&op->resource[0], 0,
 175                               resource_size(&op->resource[0]),
 176                               "fhc_pregs");
 177         if (!p->pregs) {
 178                 printk(KERN_ERR "fhc: Cannot map pregs\n");
 179                 goto out_free;
 180         }
 181 
 182         if (p->central) {
 183                 reg = upa_readl(p->pregs + FHC_PREGS_BSR);
 184                 p->board_num = ((reg >> 16) & 1) | ((reg >> 12) & 0x0e);
 185         } else {
 186                 p->board_num = of_getintprop_default(op->dev.of_node, "board#", -1);
 187                 if (p->board_num == -1) {
 188                         printk(KERN_ERR "fhc: No board# property\n");
 189                         goto out_unmap_pregs;
 190                 }
 191                 if (upa_readl(p->pregs + FHC_PREGS_JCTRL) & FHC_JTAG_CTRL_MENAB)
 192                         p->jtag_master = true;
 193         }
 194 
 195         if (!p->central) {
 196                 p->leds_resource.start = (unsigned long)
 197                         (p->pregs + FHC_PREGS_CTRL);
 198                 p->leds_resource.end = p->leds_resource.start;
 199                 p->leds_resource.name = "leds";
 200 
 201                 p->leds_pdev.name = "sunfire-fhc-leds";
 202                 p->leds_pdev.id = p->board_num;
 203                 p->leds_pdev.resource = &p->leds_resource;
 204                 p->leds_pdev.num_resources = 1;
 205                 p->leds_pdev.dev.parent = &op->dev;
 206 
 207                 err = platform_device_register(&p->leds_pdev);
 208                 if (err) {
 209                         printk(KERN_ERR "fhc: Could not register LEDS "
 210                                "platform device\n");
 211                         goto out_unmap_pregs;
 212                 }
 213         }
 214         reg = upa_readl(p->pregs + FHC_PREGS_CTRL);
 215 
 216         if (!p->central)
 217                 reg |= FHC_CONTROL_IXIST;
 218 
 219         reg &= ~(FHC_CONTROL_AOFF |
 220                  FHC_CONTROL_BOFF |
 221                  FHC_CONTROL_SLINE);
 222 
 223         upa_writel(reg, p->pregs + FHC_PREGS_CTRL);
 224         upa_readl(p->pregs + FHC_PREGS_CTRL);
 225 
 226         reg = upa_readl(p->pregs + FHC_PREGS_ID);
 227         printk(KERN_INFO "fhc: Board #%d, Version[%x] PartID[%x] Manuf[%x] %s\n",
 228                p->board_num,
 229                (reg & FHC_ID_VERS) >> 28,
 230                (reg & FHC_ID_PARTID) >> 12,
 231                (reg & FHC_ID_MANUF) >> 1,
 232                (p->jtag_master ?
 233                 "(JTAG Master)" :
 234                 (p->central ? "(Central)" : "")));
 235 
 236         err = 0;
 237 
 238 out:
 239         return err;
 240 
 241 out_unmap_pregs:
 242         of_iounmap(&op->resource[0], p->pregs, resource_size(&op->resource[0]));
 243 
 244 out_free:
 245         kfree(p);
 246         goto out;
 247 }
 248 
 249 static const struct of_device_id fhc_match[] = {
 250         {
 251                 .name = "fhc",
 252         },
 253         {},
 254 };
 255 
 256 static struct platform_driver fhc_driver = {
 257         .probe          = fhc_probe,
 258         .driver = {
 259                 .name = "fhc",
 260                 .of_match_table = fhc_match,
 261         },
 262 };
 263 
 264 static int __init sunfire_init(void)
 265 {
 266         (void) platform_driver_register(&fhc_driver);
 267         (void) platform_driver_register(&clock_board_driver);
 268         return 0;
 269 }
 270 
 271 fs_initcall(sunfire_init);

/* [<][>][^][v][top][bottom][index][help] */